I have a shopping cart system in my next.js app using Context.
I define my cart with useState
:
const [cartItems, setCartItems] = useState([]);
Then I use useEffect
to check and update the localStorage:
useEffect(() => {
if (JSON.parse(localStorage.getItem("cartItems"))) {
const storedCartItems = JSON.parse(localStorage.getItem("cartItems"));
setCartItems([...cartItems, ...storedCartItems]);
}
}, []);
useEffect(() => {
window.localStorage.setItem("cartItems", JSON.stringify(cartItems));
}, [cartItems]);
This stores the items in localStorage fine, but when I refresh, it resets the cartItems
item in localStorage to an empty array. I've seen a few answers where you get the localStorage item before setting the cart state but that throws localStorage is not defined
errors in Next. How can I do this?
setCartItems
sets the value of cartItems
for the next render, so on the initial render it's []
during the second useEffect
You can fix this by storing a ref (which doesn't rerender on state change) for whether it's the first render or not.
import React, { useState, useRef } from "react";
// ...
// in component
const initialRender = useRef(true);
useEffect(() => {
if (JSON.parse(localStorage.getItem("cartItems"))) {
const storedCartItems = JSON.parse(localStorage.getItem("cartItems"));
setCartItems([...cartItems, ...storedCartItems]);
}
}, []);
useEffect(() => {
if (initialRender.current) {
initialRender.current = false;
return;
}
window.localStorage.setItem("cartItems", JSON.stringify(cartItems));
}, [cartItems]);