Gigi101
Gigi101

Reputation: 191

Uncaught TypeError: Cannot read properties of undefined (reading 'reviews')

I'm pretty new to react, and I working on a product where I am trying to get the number of individual ratings of a product from the total number of reviews. This is in my front end in my productScreen.js:

 const getNumRating = (num) => product.reviews.filter((x) => x.rating === num).length;

The problem that I'm having is that every once in awhile I'm get a Uncaught TypeError: Cannot read properties of undefined (reading 'reviews') error on this line. Reviews comes from reviews: [reviewSchema] in my productModel.js.

I'm unsure as to why I'm getting this. In the return (); portion of my productScreen.js document, I have:{product.reviews.map((review) => (... ))}, which works fine.

Could I not be passing reviews from my backend to my fronted?

This is my ProductRouter.js document:

import express from 'express';
import expressAsyncHandler from 'express-async-handler';
import data from '../data.js';
import Product from '../models/productModel.js';
import { isAdmin, isAuth, isSellerOrAdmin } from '../utils.js';

const productRouter = express.Router();


productRouter.get(
  '/seed',
  expressAsyncHandler(async (req, res) => {
    // await Product.remove({});
    const createdProducts = await Product.insertMany(data.products);
    res.send({ createdProducts });
  })
);



productRouter.get(
  '/:id',
  expressAsyncHandler(async (req, res) => {
    const product = await Product.findById(req.params.id);
    if (product) {
      res.send(product);
    } else {
      res.status(404).send({ message: 'Product Not Found' });
    }
  })
);
productRouter.post(
    '/',
    isAuth,
    isSellerOrAdmin,
    expressAsyncHandler(async (req, res) => {
      const product = new Product({
        name: 'sample name ' + Date.now(),
      });
      const createdProduct = await product.save();
      res.send({ message: 'Product Created', product: createdProduct });
    })
  );


  productRouter.put(
    '/:id',
    isAuth,
    isSellerOrAdmin,
    expressAsyncHandler(async (req, res) => {
      const productId = req.params.id;
      const product = await Product.findById(productId);
      if (product) {
        product.name = req.body.name;
        
        const updatedProduct = await product.save();
        res.send({ message: 'Product Updated', product: updatedProduct });
      } else {
        res.status(404).send({ message: 'Product Not Found' });
      }
    })
  );
  productRouter.delete(
    '/:id',
    isAuth,
    isAdmin,
    expressAsyncHandler(async (req, res) => {
      const product = await Product.findById(req.params.id);
      if (product) {
        const deleteProduct = await product.remove();
        res.send({ message: 'Product Deleted', product: deleteProduct });
      } else {
        res.status(404).send({ message: 'Product Not Found' });
      }
    })
  );


  productRouter.post(
    '/:id/reviews',
    isAuth,
    expressAsyncHandler(async (req, res) => {
      const productId = req.params.id;
      const product = await Product.findById(productId);
      if (product) {
        if (product.reviews.find((x) => x.name === req.user.name)) {
          return res
            .status(400)
            .send({ message: 'You already submitted a review' });
        }
        const review = {
          name: req.user.name,
          rating: Number(req.body.rating),
          comment_title: req.body.comment_title,
          comment: req.body.comment,
          age: req.body.age,
          customerImages: req.body.customerImages,
       
        };
        product.reviews.push(review);
        product.numReviews = product.reviews.length;
        product.rating =
          product.reviews.reduce((a, c) => a = a +c.rating, 0) /
          product.reviews.length;
       

        const updatedProduct = await product.save();
        res.status(201).send({
          message: 'Review Created',
          review: updatedProduct.reviews[updatedProduct.reviews.length - 1],
        });
      } else {
        res.status(404).send({ message: 'Product Not Found' });
      }
     
    })
  );
  

export default productRouter;

I also tried to add numRating5 to my productModel.js, and

product.numRating5 = product.reviews.filter((x) => x.rating === 5).length;

after product.rating in productRouter.post(...) in productRouter.js, but that just gave me an Uncaught TypeError: Cannot read properties of undefined (reading 'numRating5') error in the frontend.

I would really appreciate any help or advice on how to fix this. Thank you!

Upvotes: 0

Views: 1579

Answers (1)

lpizzinidev
lpizzinidev

Reputation: 13284

The problem is probably related to the fact that the product has not been loaded from the API when you are trying to access it.
Adding a null-check should prevent the error:

const getNumRating = (num) => {
  if (!product) return 0;
  return product.reviews.filter((x) => x.rating === num).length;
}

Upvotes: 2

Related Questions