Redux reducer中更新键值对状态有没有符合习惯的简易实现方式?
解决方案
目前已经有非常成熟的方案可以简化这类不可变更新的样板代码,常用的有以下几种:
- 使用Redux Toolkit(RTK,Redux官方标准工具集)
这是当前Redux生态官方首推的开发工具,内部默认集成了Immer库,允许你用可变写法编写更新逻辑,底层会自动转换成符合Redux不可变性要求的状态更新,完全不需要手动写多层展开运算符。
示例代码:
import { createSlice } from '@reduxjs/toolkit' const kvStateSlice = createSlice({ name: 'kvState', initialState: {}, reducers: { updateTargetValue(state, action) { const { id, newValue } = action.payload // 写法和Vue的可变状态更新几乎完全一致 state[id].valueIWantToChange = newValue } } }) // 自动生成的action和reducer可以直接用 export const { updateTargetValue } = kvStateSlice.actions export default kvStateSlice.reducer
- 单独引入Immer库
如果是存量老项目暂时无法全量迁移到Redux Toolkit,也可以单独引入Immer,仅用它处理不可变更新:
import produce from 'immer' const originalReducer = (state = {}, action) => { switch (action.type) { case 'UPDATE_TARGET_VALUE': const { id, newValue } = action.payload // 用produce包裹更新逻辑,直接操作draft对象即可 return produce(state, draft => { draft[id].valueIWantToChange = newValue }) default: return state } }
也可以直接用produce包裹整个reducer,进一步简化写法:
const reducer = produce((draft, action) => { switch (action.type) { case 'UPDATE_TARGET_VALUE': const { id, newValue } = action.payload draft[id].valueIWantToChange = newValue } }, {}) // 第二个参数为初始状态
- 自行封装通用工具函数
如果不想引入额外第三方依赖,可以自己封装一个处理键值对状态更新的通用函数,消除重复的展开代码:
// 封装通用更新工具 const updateKvItem = (state, id, updater) => ({ ...state, [id]: updater({ ...state[id] }) }) // 实际使用 const yourReducer = (state = {}, action) => { switch (action.type) { case 'UPDATE_TARGET_VALUE': const { id, newValue } = action.payload return updateKvItem(state, id, item => { item.valueIWantToChange = newValue return item }) default: return state } }
目前行业内最通用的是前两种基于Immer的方案,也是Redux官方推荐的写法,完全可以解决你提到的样板代码臃肿、写法繁琐的问题。
内容的提问来源于stack exchange,提问作者nialna2
相关产品推荐
相关产品推荐

