简体   繁体   中英

React Online Store - createContext doesn't keep data on page reload

As I am learning React, I've decided to try to create my own online store. Just after learning and implementing createContext functionality and handling, I've come across the problem of it not keeping data on page refresh/reload.

The easiest solution would probably be to store the data into the localStorage, but I can't figure out how to implement and handle the localStorage item as the whole createContext (contextValue) array and keep it updated on each context's function change.

Is there any simple solution for this in React? Or what is the best JS solution in react overall to handle such context?

import { createContext, useState } from "react";
import { productsArray, getProductData } from "./productsConfig";

export const CartContext = createContext({
    items: [],
    getProductQuantity: () => {},
    addOneToCart:       () => {},
    removeOneFromCart:  () => {},
    deleteFromCart:     () => {},
    getTotalCost:       () => {}
});

export function CartProvider({children}) {
    const [cartProducts, setCartProducts] = useState([]);

    function getProductQuantity(id) {
        const quantity = cartProducts.find(product => product.id === id)?.quantity;
        
        if (quantity === undefined) {
            return 0;
        }

        return quantity;
    }

    function addOneToCart(id) {
        const quantity = getProductQuantity(id);

        if (quantity === 0) {
            setCartProducts(
                [
                    ...cartProducts,
                    {
                        id: id,
                        quantity: 1
                    }
                ]
            )
        } else { // is in cart
            setCartProducts(
                cartProducts.map(
                    product =>
                    product.id === id                               
                    ? { ...product, quantity: product.quantity + 1 }
                    : product                                       
                )
            )
        }
    }
    
    function removeOneFromCart(id) {
        const quantity = getProductQuantity(id);

        if (quantity === 1) {
            deleteFromCart(id);
        } else {
            setCartProducts(
                cartProducts.map(
                    product =>
                    product.id === id                               
                    ? { ...product, quantity: product.quantity - 1 }
                    : product                                       
                )
            )
        }
    }

    function deleteFromCart(id) {
        setCartProducts(
            cartProducts =>
            cartProducts.filter(currentProduct => {
                return currentProduct.id !== id;
            })
        )
    }

    function getTotalCost() {
        let totalCost = 0;
        cartProducts.map((cartItem) => {
            const productData = getProductData(cartItem.id);
            totalCost += (productData.price * cartItem.quantity);
        });
        return totalCost;
    }

    const contextValue = {
        items: cartProducts,
        getProductQuantity,
        addOneToCart,
        removeOneFromCart,
        deleteFromCart,
        getTotalCost
    }

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

export default CartProvider;

You should use context to manage cart internal state and use local storage to keep your cart state persistent (or you can use an session storage approach). So, use local storage to save your cartProducts array as an object

localStorage.setItem('cart', JSON.stringify(newCartProductsArray))

and update it on add/remove functions, the update function should overwrite the same key value.

To restore your state after an refresh use useEffect hook inside CartProvider.

useEffect(() => {
  const savedCartState = JSON.parse(localStorage.getItem('cart'));
  setCartProducts(savedCartState);
}, []);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM