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

React中reducer函数多次调用致计数异常,如何解决?

修复useReducer计数增量错误(每次加2)的问题

问题根源

  1. Reducer中直接修改原状态:increment-quantity逻辑里直接修改state[action.mealIndex][1]属于状态突变,违反了React对reducer纯函数的要求。在Strict Mode开发环境下,双重调用reducer会因为状态突变导致计数被重复修改。
  2. Quantity状态更新依赖旧值:setQuantity(Quantity+1)基于当前渲染周期的旧值更新,Strict Mode下组件双重渲染会让这个操作执行两次,导致每次加2。
  3. 冗余的Quantity状态:Quantity可直接从orderedMeals计算得到,单独维护容易出现状态不同步。

修复方案

1. 重构Reducer为纯函数

确保所有状态操作都返回新的数组/对象,不修改原state:

function reducer(state, action) {
  switch (action.type) {
    case "increment-quantity":
      return state.map((mealPair, index) => {
        if (index === action.mealIndex) {
          // 返回新的mealPair数组,不修改原元素
          return [mealPair[0], mealPair[1] + 1];
        }
        return mealPair;
      });
    case "decrement-quantity":
      return state.map((mealPair, index) => {
        if (index === action.mealIndex && mealPair[1] > 1) {
          return [mealPair[0], mealPair[1] - 1];
        }
        return mealPair;
      });
    case "add-meal":
      return [...state, [action.meal, 1]];
    default:
      return state;
  }
}

2. 移除冗余的Quantity状态,改为计算值

直接从orderedMeals计算总数量,避免状态不同步:

function App() {
  const [orderedMeals, dispatch] = useReducer(reducer, []);
  const [openModal, setOpenModal] = useState(false);

  const [isFetching, menu, setFetchedData, error] = useFetch(fetchMeals, []);

  // 直接计算总数量,无需单独维护状态
  const totalQuantity = orderedMeals.reduce((sum, [_, count]) => sum + count, 0);

  const onAddToCart = (meal) => {
    const mealFound = orderedMeals.find((mealPair) => mealPair[0] === meal);
    if (!mealFound) {
      dispatch({ type: "add-meal", meal: meal });
    } else {
      const mealIndex = orderedMeals.indexOf(mealFound);
      dispatch({ type: "increment-quantity", mealIndex: mealIndex });
    }
  };

  // 后续使用totalQuantity即可
}

3. (可选)保留Quantity状态的函数式更新写法

若必须单独维护Quantity,改用函数式更新确保基于最新状态:

const onAddToCart = (meal) => {
  // ... 其他逻辑不变
  setQuantity(prevQuantity => prevQuantity + 1);
};

关于Strict Mode的影响

Strict Mode在开发环境下会双重调用组件函数、reducer等,用于检测不纯操作。原代码的状态突变导致第一次调用reducer时修改了原state,第二次调用又基于已修改的state再次增量,最终出现加2的错误。修复纯函数后,两次调用都会基于原始state生成新状态,最终只会生效一次。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:13:13