You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Context结合LocalStorage刷新后数据不持久问题排查

解决React Context结合LocalStorage刷新后数据丢失的问题

你的问题出在初始渲染的执行顺序上:

  • 组件挂载时,useState先把products初始化为空数组
  • 紧接着触发监听products变化的useEffect,把空数组写入LocalStorage,直接覆盖了之前存储的数据
  • 之后读取LocalStorage的useEffect才执行,但此时LocalStorage已经被清空,读不到有效数据

修复方案

直接在useState的初始化阶段读取LocalStorage,而不是依赖额外的useEffect。useState的初始化函数只会在组件首次挂载时执行一次,完美避开覆盖问题。

修改后的核心代码:

function CartProvider({ children }: { children: ReactNode }) {
  // 直接在useState初始化时读取LocalStorage
  const [products, setProducts] = useState<CartProduct[]>(() => {
    const savedCart = localStorage.getItem("cart");
    return savedCart ? JSON.parse(savedCart) : [];
  });

  // 只保留写入LocalStorage的useEffect
  useEffect(() => {
    localStorage.setItem("cart", JSON.stringify(products));
  }, [products]);

  // addProduct和removeProduct逻辑保持不变
  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>
  );
}

额外注意事项

  • 如果你的Product类型包含无法被JSON.stringify序列化的字段(比如Date对象、函数),需要先处理这些字段再存入LocalStorage,否则会丢失数据
  • 若项目涉及服务端渲染(SSR),需要用typeof window !== 'undefined'包裹LocalStorage操作,避免在服务端执行时报错

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 11:38:11