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

React useReducer购物车Reducer中数量计算重复执行问题

问题分析与修复

你的购物车reducer出现商品数量重复累加的问题,根源在于错误的数组拷贝方式和未正确处理引用类型的状态更新,具体问题点和修复方案如下:

问题原因

  1. 数组拷贝错误:你用let newStateItems = {...newState.items}将数组转换为了键为索引的对象,而非创建数组的副本。后续将这个对象赋值给newState.items,破坏了原本的数组结构,同时因为对象引用的问题,修改newStateItems中的商品时会直接修改原状态的商品对象。
  2. 纯函数原则被破坏:Reducer必须是纯函数,不能修改原state。你的代码中通过引用修改了原state的商品数量,若遇到React严格模式(reducer会被执行两次检测副作用),就会出现重复累加的情况。

修复后的Reducer代码

const addToCartReducer = (state, action) => {
    console.log('executing reducer');

    const existingItemIndex = state.items.findIndex(
        (item) => item.restaurant === action.item.restaurant && item.menu === action.item.menu
    );

    if (action.type === 'ITEM_ADDED') {
        console.log('executing ITEM_ADDED');
        const addQuantity = parseInt(action.item.quantity);
        let newItems = [...state.items]; // 创建数组副本
        let newTotalItems = state.totalItems + addQuantity;

        if (existingItemIndex >= 0) {
            // 创建要修改的商品对象副本,避免修改原state
            const updatedItem = {
                ...newItems[existingItemIndex],
                quantity: newItems[existingItemIndex].quantity + addQuantity
            };
            newItems[existingItemIndex] = updatedItem;
        } else {
            // 新增商品时确保quantity是数字类型
            newItems.push({...action.item, quantity: addQuantity});
        }

        return {
            ...state,
            items: newItems,
            totalItems: newTotalItems
        };
    }

    return state;
};

关键修复点说明

  • 正确拷贝数组:用[...state.items]创建数组的浅副本,确保不会修改原数组引用。
  • 修改商品时创建对象副本:更新已有商品数量时,通过{...newItems[existingItemIndex], quantity: ...}创建新的商品对象,避免直接修改原state中的对象。
  • 统一计算逻辑:将数量转换和计算提前处理,避免重复解析parseInt,同时确保totalItems的计算只执行一次。
  • 纯函数实现:所有状态更新都通过创建新对象/数组完成,完全不修改原state,符合React reducer的纯函数要求。

测试你的场景:

  • 初始状态:{totalItems:1, items:[{restaurant: 'R1', menu: 'F1', quantity: 1}]}
  • 触发dispatch({type:'ITEM_ADDED', item:{restaurant:'R1', menu:'F1', quantity:2}})
  • 修复后结果:{totalItems:3, items:[{restaurant: 'R1', menu: 'F1', quantity: 3}]},与期望一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 09:20:22