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

React中LocalStorage已存购物车数据但刷新/切页后状态丢失求助

问题分析与解决方案

你的核心问题是页面刷新/切换路由后,totalQty和totalPrice状态未从localStorage同步恢复——虽然cartItem已正确加载,但这两个关键状态保持初始的0/undefined值,导致视觉上看起来购物车被重置。另外addToCart中的总价计算逻辑存在错误,会导致价格统计异常。

具体修复点

1. 初始化时同步计算总数量与总价

在读取localStorage的useEffect中,需要从加载的购物车数据里计算出对应总数量和总价,而非依赖初始值:

useEffect(() => {
  const json = localStorage.getItem('cartItem')
  const savedCart = JSON.parse(json)
  if(savedCart){
    setCartItem(savedCart);
    // 从保存的数据计算总数量和总价
    const calculatedTotalQty = savedCart.reduce((sum, item) => sum + item.quantity, 0);
    const calculatedTotalPrice = savedCart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
    setTotalQty(calculatedTotalQty);
    setTotalPrice(calculatedTotalPrice);
  }
}, []);

2. 修正addToCart中的总价计算逻辑

原代码中prevTotalPrice + prevTotalPrice*quantity是错误逻辑,应改为累加当前商品的单价乘以数量:

// 替换原错误的总价更新行
setTotalPrice((prevTotalPrice) => prevTotalPrice + (Item.price * quantity));

3. 避免直接修改原始数据对象

原代码中Item.quantity = quantity会直接修改数据源中的原对象,改用展开运算符创建新对象:

// 替换原else块内的代码
setCartItem([...cartItem, {...Item, quantity: quantity}]);

修改后的完整CartContext代码

import { createContext, useContext, useState, useEffect } from "react";

const CartContext = createContext();
export const CartProvider =({children})=>{
      
  const [cartItem, setCartItem] = useState([])
  const [qty, setQty] = useState(1);
  const [showCart, setShowCart] = useState(false);
  const [totalQty, setTotalQty] = useState(0);
  const [totalPrice, setTotalPrice] = useState(0); // 初始化为0而非undefined

  const increaseQty = ()=>{
    setQty(prevQty => prevQty+1)
  }
  const decreaseQty = () =>{
    setQty((prevQty)=>{
      if(prevQty - 1< 1)return 1
      return prevQty-1
    })
  }

  useEffect(() => {
    const json = localStorage.getItem('cartItem')
    const savedCart = JSON.parse(json)
    if(savedCart){
      setCartItem(savedCart);
      // 从保存的购物车数据计算总数量和总价
      const calculatedTotalQty = savedCart.reduce((sum, item) => sum + item.quantity, 0);
      const calculatedTotalPrice = savedCart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
      setTotalQty(calculatedTotalQty);
      setTotalPrice(calculatedTotalPrice);
    }
  }, []);

  useEffect(() => {
    const json = JSON.stringify(cartItem);
    localStorage.setItem("cartItem", json);
  }, [cartItem]);
      
  const addToCart = (Item, quantity)=>{
    const checkProduct = cartItem.find((product)=> product.id === Item.id)
    
    // 修正总价计算逻辑
    setTotalPrice((prevTotalPrice) => prevTotalPrice + (Item.price * quantity));
    setTotalQty((prevTotalQty)=> prevTotalQty + quantity)

    if(checkProduct){
      const updateCart = cartItem.map((cartProduct)=>{
        if(cartProduct.id === Item.id)return{
          ...cartProduct,
          quantity: cartProduct.quantity + quantity
        }
        return cartProduct; // 不要遗漏返回其他商品
      })
      setCartItem(updateCart);
      setQty(1);
    }else{
      // 避免修改原对象,直接在新对象中添加quantity属性
      setCartItem([...cartItem, {...Item, quantity: quantity}])
      setQty(1);
    }
  }

  const contextValue = {
    showCart,
    qty,
    totalPrice,
    increaseQty,
    decreaseQty,
    totalQty,
    addToCart,
    setShowCart,
    setCartItem,
    cartItem
  }

  return(
    <CartContext.Provider value ={contextValue}>
      {children}
    </CartContext.Provider>
  )
}
export const useCartProvider = () => useContext(CartContext)

额外优化建议

可以把计算totalQty和totalPrice的逻辑抽成自动同步,避免在addToCart中手动更新,提升可靠性:

// 添加这个useEffect,替代addToCart中的手动更新
useEffect(() => {
  const calculatedTotalQty = cartItem.reduce((sum, item) => sum + item.quantity, 0);
  const calculatedTotalPrice = cartItem.reduce((sum, item) => sum + (item.price * item.quantity), 0);
  setTotalQty(calculatedTotalQty);
  setTotalPrice(calculatedTotalPrice);
}, [cartItem]);

添加后即可移除addToCart中的setTotalPrice和setTotalQty调用,完全依赖购物车数据变化自动计算统计值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 15:12:08