I'm facing this error (repeats thousands of times until page crashes) whenever my Cart component (also shown below) is called:
index.js:1 Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
in Cart (created by Context.Consumer)
in Route (at Routes.js:24)
in Switch (at Routes.js:23)
in Router (created by BrowserRouter)
in BrowserRouter (at Routes.js:22)
in Routes (at src/index.js:5)
My Cart component:
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import Layout from "./Layout";
import { getCart } from "./cartHelpers";
import Card from "./Card";
import Checkout from "./Checkout";
const Cart = () => {
const [items, setItems] = useState([]);
useEffect(() => {
setItems(getCart());
}, [items]);
const showItems = items => {
return (
<div>
<h2>Your cart has {`${items.length}`} items</h2>
<hr />
{items.map((product, i) => (
<Card
key={i}
product={product}
showAddToCartButton={false}
cartUpdate={true}
showRemoveProductButton={true}
/>
))}
</div>
);
};
const noItemsMessage = () => (
<h2>
Your cart is empty. <br /> <Link to="/shop">Continue shopping</Link>
</h2>
);
return (
<Layout
className="container-fluid"
>
<div className="row">
<div className="col-6">
{items.length > 0 ? showItems(items) : noItemsMessage()}
</div>
<div className="col-6">
<h2 className="mb-4">Your cart summary</h2>
<hr />
<Checkout products={items} />
</div>
</div>
</Layout>
);
};
export default Cart;
useEffect
is calling getCart()
(shown below):
export const getCart = () => {
if (typeof window !== "undefined") {
if (localStorage.getItem("cart")) {
return JSON.parse(localStorage.getItem("cart"));
}
}
return [];
};
I intend for getCart
to grab the cart from the localStorage
and populate that in the state variable items
or return an empty array []
.
From my understanding, useEffect changes the page whenever the state changes and when there is any item in the dependency array it will be based on that.
Well I cant figure out why this error is happening.
I really tried understanding this error can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render
and here's what I learned so far trying to solve this:
items
, the dependency, doesn't change much. Testing adding 1 item or 0 items results in thousands of the same errorHow can I stop this error?
I just want this component to work without freezing and throwing thousands of this error upon render.
The reason is with your useEffect
dependencies:
useEffect(() => {
setItems(getCart());
}, [items]);
The problem is that you are passing [items]
and calling useEffect
while items changed. And inside useEffect you are changing items
.
Make sure if you return each time new object or array from
getItems()
react don't know that your objects are the same and calling effect again and again.
Remove items from dependencies
useEffect(() => {
setItems(getCart());
}, []);
Or if you need to access current state while changing it:
useEffect(() => {
setItems(currentItems => getCart(currentItems));
}, []);