如何让连续调用的两次useReducer dispatch操作均生效?
如何让useReducer的连续两次dispatch都生效?
这个问题我之前也碰到过,核心原因是你的reducer函数在返回新状态时没有合并原有state的属性,每次都是直接返回一个只包含当前action对应字段的新对象,导致之前的状态被覆盖了。
问题根源分析
你的reducer代码里,每次处理ONE或TWO类型的action时,都是直接返回{ a: action.payload }或{ b: action.payload }。比如:
- 第一次调用
dispatch({ type: 'ONE', payload: 'some string' })后,state变成{ a: 'some string' } - 第二次调用
dispatch({ type: 'TWO', payload: 'some other string' })时,reducer返回{ b: 'some other string' },直接替换了之前的state,所以最终state里只有b字段,a就丢失了。
这里要注意:React组件的setState传对象时会自动合并到当前state,但useReducer的reducer是纯函数,需要你手动处理状态合并逻辑——React不会帮你做这件事。
解决方法:合并原有state
修改reducer函数,在返回新状态时,先用扩展运算符...把原有state的所有属性复制过来,再覆盖需要更新的字段。修改后的代码如下:
function reducer(state, action) { switch (action.type) { case 'ONE': return { ...state, a: action.payload }; // 合并原有state,再更新a字段 case 'TWO': return { ...state, b: action.payload }; // 合并原有state,再更新b字段 default: throw new Error('You have probably mispelt the action name'); } }
这样处理后:
- 第一次dispatch后,state是
{ a: 'some string' } - 第二次dispatch时,
...state会把a属性带过来,再加上新的b属性,最终state变成{ a: 'some string', b: 'some other string' },两次dispatch的修改都生效了。
额外提示
如果你的state结构比较复杂(比如嵌套对象),要注意深层状态的更新,避免直接修改原有state(因为reducer必须是纯函数),可以使用类似的方式逐层合并,或者借助immer这类库来简化嵌套状态的更新逻辑。
内容的提问来源于stack exchange,提问作者Josh Pittman
相关产品推荐
相关产品推荐

