skip to Main Content

I’m using React Context to manage state in my application and I’m also using LocalStorage to persist some data between page refreshes. However, I’m running into an issue where the data stored in LocalStorage is not being maintained after a page refresh.
here is my code :

import { Product } from "@prisma/client";
import { ReactNode, createContext, useEffect, useState } from "react";

interface CartProduct extends Product {
  quantity: number;
}

interface Products {
  products: CartProduct[];
  addProduct: (product: Product) => void;
  removeProduct: (product: Product) => void;
}

const CartContext = createContext<Products>({
  products: [],
  addProduct: () => {},
  removeProduct: () => {},
});

function CartProvider({ children }: { children: ReactNode }) {
  const [products, setProducts] = useState<CartProduct[]>([]);

  useEffect(() => {
    const cart = localStorage.getItem("cart");
    if (cart) {
      setProducts(JSON.parse(cart));
    }
  }, []);

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

  function addProduct(product: Product) {
    const existingProduct = products.find((p) => p.id === product.id);

    if (existingProduct) {
      const updatedProducts = products.map((p) => {
        if (p.id === product.id) {
          return { ...p, quantity: p.quantity + 1 };
        } else {
          return p;
        }
      });

      setProducts(updatedProducts);
    } else {
      const newProduct = { ...product, quantity: 1 } as CartProduct;
      const updatedProducts = [...products, newProduct];

      setProducts(updatedProducts);
    }
  }

  function removeProduct(product: Product) {
    const existingProduct = products.find((p) => p.id === product.id);
    if (existingProduct && existingProduct.quantity > 1) {
      const updatedProducts = products.map((p) => {
        if (p.id === product.id) {
          return { ...p, quantity: p.quantity - 1 };
        } else {
          return p;
        }
      });
      setProducts(updatedProducts);
    } else {
      const updatedProducts = products.filter((p) => p.id !== product.id);
      setProducts(updatedProducts);
    }
  }

  const cartContextValue = { products, addProduct, removeProduct };

  return (
    <CartContext.Provider value={cartContextValue}>
      {children}
    </CartContext.Provider>
  );
}

export { CartContext, CartProvider };

I’ve also tried to remove the useEffect where im getting the cart and mantain the one where i save in the localStorage my products but after refreshing it’s still gone.

2

Answers


  1. Use state initializer function

    const [products, setProducts] = useState<CartProduct[]>(() => {
      const cart = localStorage.getItem("cart")
      return cart ? JSON.parse(card) : []
    });
    
    useEffect(() => {
      localStorage.setItem("cart", JSON.stringify(products));
    }, [products]);
    
    Login or Signup to reply.
  2. I think there is an issue with the below code block

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

    Each time page is refreshed the products are set to default which is a blank array. so a length check can be added as below which can solve your issue.

    Example

        useEffect(() => {
          if(products.length > 0){
                localStorage.setItem("cart", JSON.stringify(products));
          }
        }, [products]);
    

    Hope this will help. I have checked this locally and its working fine

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