Redux Toolkit如何更新深度嵌套数组对象中的remark_id?
Redux嵌套状态更新问题解决
问题背景
我是Redux新手,若有疏漏还请见谅。我的初始状态是一个深度嵌套的对象数组:
const initialState = { schedules: [ { "id": 1, "role_id": 1, "rules": [ { "id": 1, "module_id": 16, "remark_id": 2, }, ... ] }, ... ] }
我需要更新某个schedule对象下rules数组中的remark_id字段,尝试了以下代码但未生效:
updateRemark: (state, action) => { const { remark_id, rule_id, schedule_id } = action.payload const schedule = state.schedules.find(schedule => schedule.id == schedule_id) if (schedule) { const rule = schedule.rules.find(rule => rule.id == rule_id) if (rule) { rule.remark_id = remark_id } } },
我参考了Redux Toolkit官方关于嵌套数据更新的文档,核心内容是:Redux Toolkit集成的Immer库允许你以“可变”的写法编写状态更新逻辑,但底层会自动生成不可变的状态副本。对于嵌套数组这类复杂结构,需要确保Immer能正确追踪到状态的变更。
解决方案
问题出在直接修改find返回的对象时,Immer可能无法正确识别数组的变更(因为数组本身的引用没有改变)。推荐两种可行写法:
写法一:传统不可变更新(手动生成新数组/对象)
updateRemark: (state, action) => { const { remark_id, rule_id, schedule_id } = action.payload; // 遍历schedules数组,定位目标schedule并更新其rules state.schedules = state.schedules.map(schedule => { if (schedule.id !== schedule_id) { return schedule; // 无需修改的项直接返回原对象 } // 定位目标schedule后,遍历其rules数组更新对应rule return { ...schedule, rules: schedule.rules.map(rule => { if (rule.id !== rule_id) { return rule; } // 更新目标rule的remark_id return { ...rule, remark_id: remark_id }; }) }; }); }
写法二:Immer可变写法(更简洁)
updateRemark: (state, action) => { const { remark_id, rule_id, schedule_id } = action.payload; // 找到目标schedule的索引 const scheduleIndex = state.schedules.findIndex(s => s.id === schedule_id); if (scheduleIndex !== -1) { // 找到目标rule的索引 const ruleIndex = state.schedules[scheduleIndex].rules.findIndex(r => r.id === rule_id); if (ruleIndex !== -1) { // 直接修改对应索引的rule属性,Immer自动处理不可变更新 state.schedules[scheduleIndex].rules[ruleIndex].remark_id = remark_id; } } }
原因说明
第一种写法通过解构和map生成新的数组与对象,符合Redux不可变更新的核心要求;第二种写法利用Immer的特性,直接修改数组索引对应的元素,Immer会在底层追踪修改并生成新的状态副本,写法更直观。
原代码中,find返回的是对象代理,但直接修改对象属性时,未触发数组的引用变化,Immer无法正确标记状态变更,导致组件无法感知到状态更新。而通过修改数组索引或生成新数组的方式,能确保Immer正确追踪状态变化,从而触发组件重新渲染。
内容的提问来源于stack exchange,提问作者Subham Chakraborty
相关产品推荐
相关产品推荐

