Home > database >  localStorage resets to empty on refresh in NextJS
localStorage resets to empty on refresh in NextJS

Time:08-08

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?

CodePudding user response:

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]);

CodePudding user response:

thanks to jamesmosier for his answer on gitHub

The issue you are seeing is because localStorage (aka window.localStorage) is not defined on the server side. Next server renders your components, so when that happens and it tried to access localStorage it can't find it. You'll have to wait until the browser renders it in order to use localStorage.

full answer link here

EDIT

you can try this :

useEffect(() => {
    if (typeof window !== "undefined") {
      const storedCartItems = JSON.parse(localStorage.getItem("cartItems"));
      if(storedCartItems !== null) {
        setCartItems([...cartItems, ...storedCartItems]);
      }
    }
  }, []);

  useEffect(() => {
    if (typeof window !== "undefined") {
     window.localStorage.setItem("cartItems", JSON.stringify(cartItems));
    } 
  }, [cartItems]);
  • Related