Home > Software design >  Cannot read properties of undefined (reading 'map') in React
Cannot read properties of undefined (reading 'map') in React

Time:09-26

I'm trying to make a ecommerce site using the commerce.js library. I have already 8 products in the library API. I have a Products.js component where I'm passing those array of product objects I got from App.js and again passing single product object to the Product.js component. To do this, I'm using mapping function to pass each object as props to the Product.js component. And I'm receiving this error. I tried commenting out the mapping block and only console logged the products variable from App.js and the prop products in Products.js, there I'm getting all the 8 products so no problem in there. But I don't get it why I'm getting this error in the mapping function.

App.js

import React, { useState, useEffect } from "react";
import { commerce } from "./lib/commerce";
import { Products, Navbar } from "./components";

function App() {
  const [products, setProducts] = useState([]);

  const fetchProduct = async () => {
    const data = await commerce.products.list();
    setProducts(data);
  };
  useEffect(() => {
    fetchProduct();
  }, []);

  console.log("products", products);

  return (
    <div className="App">
      <Navbar />
      <Products products={products} />
    </div>
  );
}

export default App;

Products.js

import React from "react";
import { Grid } from "@material-ui/core";
import Product from "./Product/Product";
import useStyles from "./style";

const Products = ({ products }) => {
  const classes = useStyles();

  return (
    <main className={classes.content}>
      <div className={classes.toolbar} />
      <Grid container justifyContent="center" spacing={4}>
        {products.data.map((product) => (
          <Grid item key={product.id} xs={12} sm={6} md={4} lg={3}>
            <Product product={product} />
          </Grid>
        ))}
      </Grid>
    </main>
  );
};

export default Products;

Product.js

import React from "react";
import {
  Card,
  CardMedia,
  CardContent,
  CardActions,
  Typography,
  IconButton,
} from "@material-ui/core";
import { AddShoppingCart } from "@material-ui/icons";
import useStyles from "./styles";

const Product = ({ product }) => {
  const classes = useStyles();
  return (
    <Card className={classes.root}>
      <CardMedia
        className={classes.media}
        image={product.media.source}
        title={product.name}
      />
      <CardContent>
        <div className={classes.cardContent}>
          <Typography variant="h5" gutterBottom>
            {product.name}
          </Typography>
          <Typography variant="h5">
            {product.price.formatted_with_symbol}
          </Typography>
        </div>
        <Typography
          variant="body2"
          dangerouslySetInnerHTML={{ __html: product.description }}
        />
      </CardContent>
      <CardActions disableSpacing className={classes.cardActions}>
        <IconButton aria-label="Add to Cart">
          <AddShoppingCart />
        </IconButton>
      </CardActions>
    </Card>
  );
};

export default Product;

CodePudding user response:

Do you can to attached screen with error?

I think, you try to read data before is are loading, you can prevent this by add something like this (products.data || []).map for example.. or change default state in App.js on useState({data:[]})

CodePudding user response:

In your App.js change your fetchProduct function as follows:

const fetchProduct = async = {
    const products = await commerce.products.list();
    setProducts(products.data);
}

and then in your Products.js map over the products instead of products.data,

      {products.map((product) => (
          <Grid item key={product.id} xs={12} sm={6} md={4} lg={3}>
            <Product product={product} />
          </Grid>
      ))}

EXPLANATION:
The initial State of products is an empty array, which is passed down to the products component, where you tried products.data.map() but products is an array (initially) and there is no data property on arrays, so it threw error.
There are several ways you can get around this, but if you are only using the products data from the response then you can go with the above approach, where you map over the products not products.data and setProducts() with the products array instead of products object.

  • Related