Redux数组深层修改报错:Attempted to assign to readonly property问题求助
问题原因
你用[...transactions_list]做的是浅拷贝,只复制了数组外层的元素引用,数组内部嵌套的对象(比如data_yearly、data_monthly对应的对象)仍然和Redux store里的原状态指向同一个内存地址。而Redux的状态是只读的,不允许直接修改原状态的任何部分,所以当你尝试修改嵌套对象里的data_monthly时,实际上是在操作Redux原状态的只读属性,因此抛出错误。
解决方法
方法1:手动逐层拷贝嵌套结构
逐层复制所有嵌套的对象和数组,确保每一层都是新的引用,避免触碰原Redux状态:
const my_function = () => { // 复制外层数组,仅修改目标年份的内容 let new_transactions_list = transactions_list.map((item, idx) => { if (idx !== yearIndex) return item; // 复制目标年份的data_yearly数组,仅修改目标月份的内容 const newDataYearly = item.data_yearly.map((monthItem, monthIdx) => { if (monthIdx !== monthIndex) return monthItem; // 复制目标月份的data_monthly数组并添加新元素 return { ...monthItem, data_monthly: [...monthItem.data_monthly, new_obj] }; }); return { ...item, data_yearly: newDataYearly }; }); // 最后必须通过dispatch将新状态更新到Redux store // dispatch(updateTransactions(new_transactions_list)); };
方法2:用Immer简化不可变更新
Immer可以让你用“看起来可变”的写法实现不可变更新,底层自动处理深拷贝,代码更简洁:
先安装Immer:
npm install immer
再修改代码:
import { produce } from 'immer'; const my_function = () => { const new_transactions_list = produce(transactions_list, draft => { // 直接修改draft即可,Immer会自动生成新的不可变状态 draft[yearIndex].data_yearly[monthIndex].data_monthly.push(new_obj); }); // 同样需要dispatch更新Redux状态 // dispatch(updateTransactions(new_transactions_list)); };
关键注意点
不管用哪种方法,都不能直接修改Redux返回的原状态,必须生成全新的状态对象后,通过dispatch发送给reducer来更新store。
内容的提问来源于stack exchange,提问作者MehdiNasiriPoor
相关产品推荐
相关产品推荐

