You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 13:10:45