skip to Main Content

I am using Context API to pass my Cart data to different pages, and trying to use localStorage to set and retrieve the Cart data while refreshing the page.

Setting the Cart data to localStorage after every change of the state is working fine, but the problem is that when the page is refreshed, the data of localStorage is gone and so the Cart data will be reset!

I don’t understand where I’m doing something wrong and why localStorage data won’t be set and used while page is refreshed. Can you please help me out with this? (For display purposes I’m just logging the localStorage value for now.)

Here is my code:

function CartProvider({ children }: Props) {
  const [state, dispatch] = useReducer(reducer, initialState);

  const [retrievedState, setRetrievedState] = useState(
    JSON.parse(localStorage.getItem("cart") || "") || initialState
  );

  useEffect(() => {
    localStorage.setItem("cart", JSON.stringify(state));
    setRetrievedState(state);
  }, [state]);

  console.log(retrievedState);

  return (
    <CartContext.Provider value={{ state, dispatch }}>
      {children}
    </CartContext.Provider>
  );
}

2

Answers


  1. Chosen as BEST ANSWER

    So I found out that the solution for this issue is that we retrieve the state from localStorage when the component mounts (won't be needing retrievedState and it's setRetrievedState anymore), and if a value is found, we dispatch an action to hydrate the state with this value, and we update localStorage whenever the state changes, like so:

    useEffect(() => {
        const storedState = localStorage.getItem("cart");
        if (storedState) {
          dispatch({ type: "HYDRATE_STATE", payload: JSON.parse(storedState) });
        }
      }, []);
    
      useEffect(() => {
        localStorage.setItem("cart", JSON.stringify(state));
      }, [state]);
    

    And of course we should add a 'HYDRATE_STATE' action appropriately to set the state with the payload. Something like this:

    case "HYDRATE_STATE":
          return action.payload;
    

  2. In context provider, when you refresh, all values are set to empty/ initial state.

    In your code you are using useEffect, so on first render you are setting the localStorage to a value from state.

    useEffect(() => {
        localStorage.setItem("cart", JSON.stringify(state));
        setRetrievedState(state);
      }, [state]);
    

    If state is not already defined, then its going to set localStorage to empty, and when you change the state, localStorage is set again.

    You should be inspecting the state variable and make sure that it has some values when page refreshes. Other than that I don’t see any flaws in the code.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search