I’m using the following code to store cart data into local storage
"use client";
import React, { useState, useEffect } from "react";
export default function Home() {
const [cartItems, setCartItems] = useState([]);
useEffect(() => {
const cartItemsData = JSON.parse(localStorage.getItem("cartItems"));
if (cartItemsData) {
console.log("loaded cart items data", cartItemsData);
setCartItems(cartItemsData);
}
}, []);
useEffect(() => {
console.log("storing cart items", JSON.stringify(cartItems));
localStorage.setItem("cartItems", JSON.stringify(cartItems));
}, [cartItems]);
return <div>{JSON.stringify(cartItems)}</div>;
}
The issue I’m having is that when the page reloads, there is a race condition as it calls the use effect hook which pulls the data from local storage and after it calls the use effect hook with cartItems=[] from the initialisation of useState([]) which then wipes local storage and sets cartItems to [].
I tried loading the data from local storage in useState but I get an error as the window hasn’t loaded at that point.
How do I fix this?
Interestingly if I set useState(""), it seems to work ok as in this case, the setCartItems is called after the initial use effect fires.
3
Answers
To fix this issue, you can initialize the state with a function that retrieves the data from localStorage only once when the component mounts. This avoids the problem of initializing with an empty array and then overwriting the state and localStorage.
Another alternative
useLocalStorageState from aHooks
you can use this code for this issue
When you initialize the cartItems’s state with an empty array
([])
, theuseEffect
that read fromlocalStorage
will run after the initial render. This means the initial state will be an empty array, and theuseEffect
that writes tolocalStorage
will immediately store this empty array before theuseEffect
that reads fromlocalStorage
can update the state with the actual data.On the other hand, when you initialize the cartItems’s state with an empty string
("")
, the initial state is not an empty array, so it do not trigger the same immediate overwrite behavior. This can cause theuseEffect
that reads fromlocalStorage
to run and set the state before theuseEffect
that writes tolocalStorage
can overwrite it.The solutiuon can be to initialize state with
localStorage
data or an emptyarray
if no data is found.