Samuel Antwi
Samuel Antwi

Reputation: 33

How to setup and use local storage in next js

Can somebody help me to solve an issue with Next JS and localstorage. I am building an ecommerce app where when a user puts an item in their basket, I want to be able to save it to the local storage. My current implementation doesn't work and I am geting an error that says 'Cannot read property 'basket' of undefined'. Below is my code snippet.

export const StateProvider = ({ children }) => {
  const initialState = () => {
    if (typeof window !== 'undefined') {
      return {
        basket:
          window.localStorage.getItem('basket') === null
            ? []
            : window.localStorage.getItem('basket'),
        viwedItems: [],
        saved: [],
      };
    }
  };

  const [state, dispatch] = useReducer(productReducer, initialState());
  const [durationNotification, setDurationNotification] = useState(true);
  const [showMiniBasket, setMiniBasket] = useState(false);

  useEffect(() => {
    window.localStorage.setItem('basket', state.basket);
  }, [state.basket]);

Upvotes: 2

Views: 4787

Answers (1)

juliomalves
juliomalves

Reputation: 50278

The issue occurs because state is undefined when running on the server, so it'll throw an error when setting the value on the useEffect's dependency array: [state.basket].

There are several ways this could be fixed, but one of them is to return an empty object from initialState if typeof window !== 'undefined' is false.

export const StateProvider = ({ children }) => {
    const initialState = () => {
        if (typeof window !== 'undefined') {
            return {
                basket:
                window.localStorage.getItem('basket') === null
                    ? []
                    : window.localStorage.getItem('basket'),
                viwedItems: [],
                saved: [],
            };
        }
        return {
            basket: [],
            viewedItems: [],
            saved: []
        }; // Add this so `state` is not undefined on the server-side
    };

    const [state, dispatch] = useReducer(productReducer, initialState());

    useEffect(() => {
        window.localStorage.setItem('basket', state.basket);
    }, [state.basket]); // Accessing `state.basket` will no longer throw an error
    //...
}

Upvotes: 2

Related Questions