ocom
ocom

Reputation: 141

Why am I Getting the Error: Invalid Hook Call?

I'm receiving a cannot read props of undefined. I'm trying to destructure props but I need the hook calls. Is there a way for me to destructure props in a function or another way to resolve this issue?

ProductBrowse.jsx is formatting the products:

    const ProductBrowse = () => {

    const { id, name, img, store, price, desc, inCart } = this.props.product;
    const [open, setOpen] = React.useState(false);

    const openModal = () => {
      setOpen(!open);
    };

    const closeModal = () => {
      setOpen(!open);
    };

    return (
      <Box border={1} borderRadius={3}>
        <Card>
          <CardActionArea>
             <ProductModal
              open={open}
              onClick={() => openModal()}
              onClose={() => closeModal()}
              onSave={() => closeModal()}
              productName={name}
              productDesc={desc}
            />
            <CardHeader
              title={name}
              subheader={formatCurrency(price)}
            />
            <CardMedia
              image={img}
              alt={desc}
            />
            <CardContent>
              <Typography variant='body2' color='textSecondary' component='p'>
                {desc}
              </Typography>
            </CardContent>
          </CardActionArea>
          <CardActions>
            <Button size='small' /*To Checkout*/>BUY NOW</Button>
            <Button
              size='small'
              onClick={() => {
                console.log('Added to Cart');
              }}
            >
              ADD TO CART
            </Button>
            <Button size='small'>REVIEW</Button>
          </CardActions>
        </Card>
      </Box>
    );
  }

Upvotes: 1

Views: 216

Answers (2)

Rohitha
Rohitha

Reputation: 759

You are trying to use hooks in class based components. Please refer converted functional component

const ProductBrowse = props => {
  const { id, name, img, store, price, desc, inCart } = props.product;
  const [open, setOpen] = useState(false);

  const classes = useStyles();

  const openModal = () => {
    setOpen(!open);
  };

  const closeModal = () => {
    setOpen(!open);
  };

  return (
    <Box border={1} borderRadius={3}>
      <Card>
        <CardActionArea>
          {<ProductModal
            open={open}
            onClick={() => openModal()}
            onClose={() => closeModal()}
            onSave={() => closeModal()}
            productName={name}
            productDesc={desc}
          /> }
          <CardHeader title={name} subheader={formatCurrency(price)} />
          <CardMedia image={img} alt={desc} /> 
          <CardContent>
            <Typography variant="body2" color="textSecondary" component="p">
              {desc}
            </Typography>
          </CardContent>
        </CardActionArea>
        <CardActions>
          <Button size="small" /*To Checkout*/>BUY NOW</Button>
          <Button
            size="small"
            onClick={() => {
              console.log("Added to Cart");
            }}
          >
            ADD TO CART
          </Button>
          <Button size="small">REVIEW</Button>
        </CardActions>
      </Card>
    </Box>
  );
};

Also while using this components pass product as it's props as you are destructuring in ProductBrowse component. It should be like this:

<ProductBrowse products={this.products} />

Upvotes: 1

Phobos
Phobos

Reputation: 1646

You can convert your class based component to a functional component like this:

const ProductBrowse = ({ product }) => {

   const { id, name, img, store, price, desc, inCart } = product;
   ...
}
export default ProductBrowse;

As you can see, the product props are being destructured. The entire props object is available if you were to provide more props and want to use them as well.

i.e.

const ProductBrowse = (props) => {

   const { id, name, img, store, price, desc, inCart } = props.product;
   ...
}
export default ProductBrowse;

Upvotes: 1

Related Questions