LocalStorage doesn't stay updated on page refresh in MERN Application

Viewed 75

LocalStorage somehow doesn't want to stay updated on refresh page. I'm not sure why is that happening, and where is my mistake. The backend is updating fine but the localStorage doesn't stay updated.

Here is where I'm updating localStorage:

    const UserContextProvider = (props) => {
    const [user, setUser] = useState({})
    const [cart, setCart] = useState(localStorage.getItem("cart") || [])
    
    useEffect(() => {
        fetch(`${API}/auth/user`, {
            method: 'GET',
            withCredentials: true,
            credentials: 'include'
        })
        .then (response => response.json())
        .then (response => {
            setUser(response.user)
        })
        .catch (error => {
            console.error (error);
        });
    }, [setUser])
    

    useEffect(() => {
        localStorage.setItem("cart", JSON.stringify(user.cart))
    }, [setUser])

    const addToCart = (user, product) => {
        fetch(`${API}/cart/usercart`, {
            method:"POST",
            headers: { 
                'Content-Type': 'application/json'
            },
        body: JSON.stringify([user._id, product])
        })
        .then(() => setUser({...user, cart: [...user.cart, product]}))
        .catch(error => console.log(error))
    }

    return (
        <UserProvider value={[user, setUser, addToCart, cart]}>
            {props.children}
        </UserProvider>
    )
}   

export default UserContextProvider;

And here is the component where I'm trying to use it:

const Cart = props => {
    
    const [user, setUser, cart] = useContext(UserContext)  

...

{cart?.length === 0 ? <></> :
                <>
                {cart?.map(product => {
                    return(...)
1 Answers

The following code only runs once when the component mounts:

useEffect(() => {
  setCart(JSON.parse(localStorage.getItem("cart")) || [])
}, []);

In order to render the latest value you'll have to depend on a prop or something that updates when cart updates:

useEffect(() => {
  setCart(JSON.parse(localStorage.getItem("cart")) || [])
}, [props.something]);

Based on your implementation, I'd recommend having your contextProvider provide this data instead of component itself retrieving it from localStorage on each render. You only need the localStorage value when the app starts.

Related