【问题标题】:React: Setting state to local storageReact:将状态设置为本地存储
【发布时间】:2022-01-19 17:19:10
【问题描述】:

我正在请求帮助将 cartItems 状态设置为本地存储,以便当我从不刷新时,我仍然可以获得项目。

import React, { createContext, useState } from 'react';

export const AppContext = createContext();

export function Context(props) {
  const [cartItems, setCartItems] = useState([]);

  const cart = (item) => {
    const exist = cartItems.find((x) => x.id === item.id);
    if (!exist) {
      setCartItems([...cartItems, { ...item }]);
    } else {
      alert('Item Already Taken');
    }
  };

  const onAdd = (items) => {
    console.log(cartItems);
    const exist = cartItems.find((x) => x.id === items.id);
    if (exist) {
      setCartItems(
        cartItems.map((x) =>
          x.id === items.id ? { ...exist, qty: exist.qty + 1 } : x,
        ),
      );
      console.log(cartItems);
    } else {
      console.log(items);
      setCartItems([...cartItems, { ...items, qty: 1 }]);
    }
  };

  const onRemove = (product) => {
    const exist = cartItems.find((x) => x.id === product.id);
    if (exist.qty === 1) return;
    setCartItems(
      cartItems.map((x) =>
        x.id === product.id ? { ...exist, qty: exist.qty - 1 } : x,
      ),
    );
  };

  const onDeleted = (product) => {
    if (window.confirm('Do you want to delete this product?')) {
      setCartItems(cartItems.filter((x) => x.id !== product.id));
    }
  };

  const itemPrice =
    cartItems && cartItems.reduce((a, c) => a + c.qty * c.price, 0);
  const delieveryPrice = '3000';
  // eslint-disable-next-line
  const totalPrice =
    parseInt(itemPrice) + (itemPrice && parseInt(delieveryPrice));

  return (
    <AppContext.Provider
      value={{
        cartItems,
        setCartItems,
        onAdd,
        onRemove,
        cart,
        onDeleted,
        itemPrice,
        totalPrice,
        delieveryPrice,
      }}
    >
      {props.children}
    </AppContext.Provider>
  );
}

【问题讨论】:

  • 添加一个使用cartItems depndecy的useEffect,并保存到useEffect里面的localStorage
  • 你自己尝试过什么?我在您的代码 sn-p 中看不到任何 localStorage 调用。 stackoverflow.com/help/minimal-reproducible-example 在更新时将您的购物车状态保存到 localStorage,当上下文挂载时从 localStorage 初始化购物车状态。

标签: javascript reactjs local-storage react-context


【解决方案1】:

您可以通过创建 customHook 来使用 localStorage 中的值初始化状态并在每次更新时在 localStorage 上写入状态来实现您的目标,如下所示:

import * as React from 'react'
function useLocalStorageState(
  key,
  defaultValue = '',
  {serialize = JSON.stringify, deserialize = JSON.parse} = {},
) {
  const [state, setState] = React.useState(() => {
    const valueInLocalStorage = window.localStorage.getItem(key)
    if (valueInLocalStorage) {
      try {
        return deserialize(valueInLocalStorage)
      } catch (error) {
        window.localStorage.removeItem(key)
      }
    }
    return typeof defaultValue === 'function' ? defaultValue() : defaultValue
  })

  const prevKeyRef = React.useRef(key)

  React.useEffect(() => {
    const prevKey = prevKeyRef.current
    if (prevKey !== key) {
      window.localStorage.removeItem(prevKey)
    }
    prevKeyRef.current = key
    window.localStorage.setItem(key, serialize(state))
  }, [key, state, serialize])

  return [state, setState]
}

并像这样在您的组件中使用它:

const [cartItems, setCartItems] = useLocalStorageState('cartItems',[]);

【讨论】:

    【解决方案2】:
    You use can use localStorage.setItem().but since you have a list of items, you will first stringify it while saving and parsing when you fetch it back.
                    
                    
        import React, { createContext, useState } from 'react';
         export const AppContext = createContext();
                      
          export function Context(props) {
                 const [cartItems, setCartItems] = useState([]);
                 const onAdd = (items) => {
                 const tempItems = [...cartItems];
                 const exist = cartItems.findIndex((x) => x.id === items.id);
                 console.log(exist);
                 if (exist >= 0) {
                 tempItems[exist].qty = tempItems[exist].qty + 1;
                        } 
                 else {
                 // setCartItems([...cartItems, { ...items, qty: 1 }]);       
                  tempItems.push(items)
                   }
                 setCartItems(tempItems)
                 localStorage.setItem("cart" , JSON.stringify(tempItems))
                      };
                        
        //to fetch data
        const getCart = () => {
            const FetchedcartItems = localStorage.getItem("cart");
            if (FetchedcartItems) {
              const parsedCartItems = JSON.parse(FetchedcartItems);
              console.log(parsedCartItems);
              setCartItems(parsedCartItems);
            }
          };
        
          useEffect(() => {
            getCart();
          }, []);
            
        
                          return (
                            <AppContext.Provider
                              value={{
                                cartItems,
                                setCartItems,
                                onAdd,
                                onRemove,
                                cart,
                                onDeleted,
                                itemPrice,
                                totalPrice,
                                delieveryPrice,
                              }}
                            >
                              {props.children}
                            </AppContext.Provider>
                          );
                        }
    

    【讨论】:

      【解决方案3】:

      我所做的通常是设置一个文件来处理 localStorage,所以在你的情况下,cart.services.js。在该文件中,您可以创建接收、保存、读取、修改等 localStorage 的函数。

      类似这样的:

      const getCart = () => {
        return JSON.parse(localStorage.getItem("cart"));
      };
      
      const setCart = (cart) => {
        localStorage.setItem("cart", JSON.stringify(cart));
      };
      
      const removeUser = () => {
        localStorage.removeItem("cart");
      };
      

      显然,您可能需要一些更奇特的逻辑来根据以前的状态添加项目等,但基本逻辑就是这样,而且非常简单。

      更多信息:https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

      【讨论】:

      • 如果 localStorage 为空,getCart 可能会崩溃!
      • @sojin 我刚刚展示了如何使用 localStorage 的基本概念,OP 需要围绕验证和捕获实现自己的逻辑。
      猜你喜欢
      • 2017-06-11
      • 1970-01-01
      • 2018-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 2020-11-02
      相关资源
      最近更新 更多