我有一个 useReducer 状态,它是一个包含数字数组的对象。当我尝试增加 reducer 中的其中一个数字时,它会增加 2?

I have a useReducer state that's an object holding an array of numbers. When I try to increment one of those numbers in the reducer, it goes up by 2?

这是我的反应组件和我的减速器功能:

const testReducer = (state) => {
  const newState = {...state}
  newState.counts[0] += 1

  return newState
}

function App() {
  const [countState, dispatchCount] = useReducer(testReducer, {counts: [0]})

  return (
    <div className="App">
      <h1>{countState.counts[0]}</h1>
      <button onClick={dispatchCount}>up</button>
    </div>
  );
}

单击按钮并执行 reducer 时,我希望 H1 中显示的计数增加 1。第一次单击该按钮时会发生这种情况,但每次后续单击都会将其递增 2。

无论将计数初始化为什么,都会发生这种情况。如果我递增的值不在数组中,它可以正常工作。

谁能告诉我为什么会这样?

问题

newState.counts[0] = += 1 不是有效语法。假设你的意思是 newState.counts[0] += 1 那么你正在改变状态对象。

const testReducer = (state) => {
  const newState = {...state}
  newState.counts[0] += 1 // <-- mutates newState.counts!!

  return newState
}

很可能通过在 React.StrictMode 组件中呈现这种变化而暴露在您的应用中。

StrictMode - Detecting unexpected side effects

Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:

  • Class component constructor, render, and shouldComponentUpdate methods
  • Class component static getDerivedStateFromProps method
  • Function component bodies
  • State updater functions (the first argument to setState)
  • Functions passed to useState, useMemo, or useReducer <-- this

解决方案

即使您处于浅复制状态,您仍然需要 return 一个新的 counts 数组引用。

const testReducer = (state) => {
  const newState = {
    ...state,
    counts: [state.counts[0] + 1]
  };

  return newState;
};