Redux Reducer疑问:为何无法直接用state=更新整个状态?
核心结论
没办法通过state = action.payload这种直接赋值的方式更新整个状态,但有更简洁的等效写法——直接返回新状态对象(比如return action.payload),完全能满足一次性更新整个状态的需求。
为什么直接给state赋值无效?
Redux Toolkit(RTK)的reducer里传入的state参数,不是原始状态的直接引用,而是Immer库给原始状态套的一层「追踪壳」(Proxy代理对象)。这个壳的作用是追踪你对state属性的修改,自动生成符合Redux要求的不可变新状态。
当你写state = action.payload时,本质上只是修改了当前reducer函数内部的局部变量state的指向,让它从指向「追踪壳」变成指向action.payload。但这个操作完全没被「追踪壳」捕捉到,Immer根本不知道你要更新状态,所以最终不会生成任何新状态,Redux也不会触发组件重新渲染。
而当你修改state.userName = action.payload.name这类属性时,「追踪壳」会立刻拦截这个赋值操作,记录下你的修改,等reducer执行完毕后,自动基于原始状态生成一个包含这些修改的新的不可变对象——这就是为什么直接修改属性能生效。
更简洁的全状态更新写法
如果你的action.payload结构和当前state完全一致,不需要额外处理,直接返回它就行,这是最简洁易读的全状态更新方式:
setVariasCosas: (state, action) => { return action.payload }
如果需要对payload做一些小调整再更新,比如新增或修改某个属性,可以用对象扩展运算符生成新状态:
setVariasCosas: (state, action) => { return { ...action.payload, // 示例:额外添加最后更新时间 lastUpdated: Date.now() } }
补充说明
RTK允许两种合规的状态更新方式:
- 修改「追踪壳」的属性:借助Immer自动生成不可变状态,适合局部更新。
- 直接返回新状态对象:跳过Immer的追踪逻辑,直接用返回值作为新状态,适合全状态替换。
这两种方式都符合RTK的设计规范,根据你的需求选择即可——全状态更新的话,直接返回payload是最优解。
内容的提问来源于stack exchange,提问作者ferter3006

