0

I am working on a react shopping e-commerce website and i am using useContext and useReducer to set my cart state but each time i add to cart and reload the page my cart clears and reinitialize

each time it sets the state on reload it reinitialise it and i need the data to persist

MY CART STATE

const CartState = ({ children }) => {
  let items = [];
  const initialState = {
    showCart: false,
    products: items,
    cartItems: [],
  };
  const { q } = useQuery({
    queryKey: ["products"],
    queryFn: async () => {
      const data = await getDocs(collection(db, "/products"));
      data.docs.forEach((doc) => {
        let key = doc.id;
        let item = doc.data();
        items.push({ key, item });
      });
    },
  });

  const [state, dispatch] = useReducer(CartReducer, initialState);
  const addToCart = (item) => {
    dispatch({ type: ADD_TO_CART, payload: item });
  };
  const showHideCart = () => {
    dispatch({ type: SHOW_HIDE_CART });
  };
  const removeItem = (id) => {
    dispatch({ type: REMOVE_ITEM, payload: id });
  };
  return (
    <ShopContext.Provider
      value={{
        showCart: state.showCart,
        products: state.products,
        cartItem: state.cartItems,
        addToCart,
        showHideCart,
        removeItem,
      }}
    >
      {children}
    </ShopContext.Provider>
  );
};

MY USEREDUCER COMPONENT

import { SHOW_HIDE_CART, ADD_TO_CART, REMOVE_ITEM } from "../types";

const CartReducer = (state, action) => {
  switch (action.type) {
    case SHOW_HIDE_CART: {
      return { ...state, showCart: !state.showCart };
    }
    case ADD_TO_CART: {
      return { ...state, cartItems: [...state.cartItems, action.payload] };
    }
    case REMOVE_ITEM: {
      return {
        ...state,
        cartItems: state.cartItems.filter((item) => item.id !== action.payload),
      };
    }

    default:
      return state;
  }
};

export default CartReducer;
3
  • Have you added import { SHOW_HIDE_CART, ADD_TO_CART, REMOVE_ITEM } from "../types"; into the CarState function?
    – The KNVB
    Commented Apr 12 at 9:29
  • In the CartReducer function, have you added the console.log(action.type) to print the value of action.type?
    – The KNVB
    Commented Apr 12 at 9:31
  • yes i have imported it to my cart state
    – boop
    Commented Apr 12 at 10:43

1 Answer 1

-1

To persist the cart state across page reloads, you can use the browser's localStorage to save the cart data. Here's how you can modify your CartState component to achieve this:

import React, { useEffect, useReducer } from "react";
import { getDocs, collection } from "firebase/firestore";
import { db } from "../firebase";
import { useQuery } from "react-query";
import CartReducer from "./CartReducer";

const CartState = ({ children }) => {
  // Load cartItems from localStorage if available, or initialize to an empty array
  const cartItemsFromStorage = localStorage.getItem("cartItems");
  let items = cartItemsFromStorage ? JSON.parse(cartItemsFromStorage) : [];
  
  const initialState = {
    showCart: false,
    products: [], // Assuming this is set by the query and does not need to persist
    cartItems: items,
  };
  
  const { q } = useQuery({
    queryKey: ["products"],
    queryFn: async () => {
      const data = await getDocs(collection(db, "/products"));
      const products = data.docs.map((doc) => ({
        key: doc.id,
        item: doc.data(),
      }));
      return products;
    },
  });

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

  // Save cartItems to localStorage whenever it changes
  useEffect(() => {
    localStorage.setItem("cartItems", JSON.stringify(state.cartItems));
  }, [state.cartItems]);

  const addToCart = (item) => {
    dispatch({ type: ADD_TO_CART, payload: item });
  };
  const showHideCart = () => {
    dispatch({ type: SHOW_HIDE_CART });
  };
  const removeItem = (id) => {
    dispatch({ type: REMOVE_ITEM, payload: id });
  };
  return (
    <ShopContext.Provider
      value={{
        showCart: state.showCart,
        products: state.products,
        cartItem: state.cartItems,
        addToCart,
        showHideCart,
        removeItem,
      }}
    >
      {children}
    </ShopContext.Provider>
  );
};

This modification adds a useEffect hook that listens for changes in the cartItems state and saves it to localStorage. It also initializes the cartItems state from localStorage if available. This way, the cart items will persist across page reloads.

0

Not the answer you're looking for? Browse other questions tagged or ask your own question.