I'm creating a e-commerce website. But i'm unable to update the total price using the useState hook of react.
When is use forEach to update total price it give me this error: Uncaught (in promise) Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
codes:
import { Container, Grid, Typography } from "@mui/material";
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import useAuth from "../../../hooks/useAuth";
import Cart from "../Cart/Cart";
import CartProduct from "../CartProduct/CartProduct";
const CartContainer = () => {
const { user } = useAuth();
// useNavigate hook
const navigate = useNavigate();
/* states */
const [products, setProducts] = useState([]);
const [quantity, setQuantity] = useState(0);
const [isDeleted, setIsDeleted] = useState(false);
const [total, setTotal] = useState(0);
const handleAddQuantity = () => {
setQuantity(quantity + 1);
};
const handleRemoveQuantity = () => {
if (quantity === 0) {
return;
} else {
setQuantity(quantity - 1);
}
};
const handleDelete = (id) => {
fetch(`https://limitless-crag-38673.herokuapp.com/cart?id=${id}`, {
method: "DELETE",
})
.then((res) => res.json())
.then((data) => {
data.deletedCount > 0 && setIsDeleted(true);
alert("successfully deleted");
});
};
useEffect(() => {
setIsDeleted(false);
fetch(
`https://limitless-crag-38673.herokuapp.com/cart/product?email=${user.email}`
)
.then((res) => res.json())
.then((data) => setProducts(data));
}, [isDeleted]);
return (
<>
{/* main cart */}
<Container sx={{ my: 3 }} maxWidth="xl">
<Grid container spacing={{ xs: 1, md: 2 }}>
{/* products */}
<Grid item md={8} xs={12}>
{/* cart title */}
<Grid
container
sx={{
borderBottom: "1px solid gray",
display: { xs: "none", sm: "flex" },
}}
>
<Grid item md={6}>
<Typography variant="h5">Product</Typography>
</Grid>
<Grid item md={4}>
<Typography variant="h5" sx={{ textAlign: "center" }}>
Price
</Typography>
</Grid>
{/* <Grid item md={2}>
<Typography variant="h5" sx={{ textAlign: "center" }}>
Quantity
</Typography>
</Grid>
<Grid item md={2}>
<Typography variant="h5" sx={{ textAlign: "center" }}>
Subtotal
</Typography>
</Grid> */}
<Grid item md={2}>
<Typography variant="h5" sx={{ textAlign: "center" }}>
Cancel
</Typography>
</Grid>
</Grid>
{/*============
product
============= */}
{products.map((product) => (
<CartProduct
key={product._id}
product={product}
handleDelete={handleDelete}
total={total}
setTotal={setTotal}
/>
))}
</Grid>
{/*===========
cart
================ */}
<Cart />
</Grid>
</Container>
</>
);
};
export default CartContainer;
`And when I try this it gives me this error: Uncaught (in promise) Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
codes:
import CancelOutlinedIcon from "@mui/icons-material/CancelOutlined";
import { Grid, IconButton, Typography } from "@mui/material";
import { Box } from "@mui/system";
import React from "react";
const CartProduct = ({ product, handleDelete, setTotal, total }) => {
const { name, price, src } = product;
setTotal(total + price);
return (
<Grid
container
sx={{
borderBottom: "1px solid gray",
display: "flex",
flexDirection: { xs: "column", md: "row" },
alignItems: "center",
}}
spacing={{ md: 2, xs: 1 }}
>
{/* product */}
<Grid
sx={{
display: "flex",
alignItems: "center",
flexDirection: { md: "row", xs: "column" },
}}
item
md={6}
xs={12}
>
<Box>
<img src={src} alt="" />
</Box>
<Typography sx={{ ml: 1 }} variant="h6">
{name}
</Typography>
</Grid>
{/* Price */}
<Grid
item
md={4}
sx={{
alignItems: "center",
justifyContent: "center",
display: "flex",
}}
>
<Typography variant="h5">$ {price}</Typography>
</Grid>
{/*
// quantity
<Grid
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
}}
item
md={2}
xs={12}
>
<IconButton onClick={handleRemoveQuantity}>
<RemoveCircleOutlineOutlinedIcon />
</IconButton>
<TextField value={quantity} />
<IconButton onClick={handleAddQuantity}>
<AddCircleOutlineOutlinedIcon />
</IconButton>
</Grid>
// Subtotal
<Grid
item
md={2}
xs={12}
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<Typography variant="h5">$ {product.price}</Typography>
</Grid> */}
{/* Cancel */}
<Grid
item
md={2}
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<IconButton onClick={() => handleDelete(product._id)}>
<CancelOutlinedIcon fontSize="large" />
</IconButton>
</Grid>
</Grid>
);
};
export default CartProduct;