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

将useState数据存入Redux Toolkit后setState报错:无法赋值只读属性

问题原因与解决方案

核心问题

Redux Toolkit 默认会冻结存储在 store 中的状态对象(防止直接修改违反不可变原则)。当你把组件的 listData 直接 dispatch 到 Redux 后,组件内的 listData 和 Redux store 里的对象是同一个引用,这个对象会被 Redux 标记为只读。后续调用 changeName 时直接修改该对象的属性,就会触发 Cannot assign to read only property 错误。

具体解决方案

1. 切断组件 state 与 Redux state 的引用

在提交到 Redux 时,先对 listData 做深拷贝,避免原对象被 Redux 冻结后影响组件内的修改:

const submit = ()=>{
  // 深拷贝原数据,切断引用
  const copiedData = JSON.parse(JSON.stringify(listData));
  dispatch(changeNameArr(copiedData));
}

2. 修正组件内的状态修改逻辑

确保每次修改组件 state 时,都是基于原状态的深拷贝进行修改,不直接触碰原对象:

const changeName = () =>{
  setListData(prevState => {
    // 深拷贝原状态,生成可修改的新对象
    const newState = JSON.parse(JSON.stringify(prevState));
    
    if (notepadList[1] === undefined) {
      newState.orderItem[notepadList[0]].price = value;
    } else {
      newState.orderItem[notepadList[0]].orderItemsOptions[notepadList[1]].price = value;
    }
    
    return newState;
  });
}

3. 规范 Redux Reducer 写法(基于 Redux Toolkit 的 Immer)

Redux Toolkit 内置 Immer,支持直接修改 draft state,不需要手动展开对象,以下是正确的 reducer 写法(根据你的业务需求选择):

// 假设使用 createSlice 创建 slice
const yourSlice = createSlice({
  name: 'yourSlice',
  initialState: {
    list: [] // 初始状态根据业务调整
  },
  reducers: {
    // 如果是向 list 数组添加新数据
    changeNameArr: (state, action) => {
      state.list.push(action.payload);
    },
    // 如果是替换整个 list 对象
    // changeNameArr: (state, action) => {
    //   state.list = action.payload;
    // }
  }
});

验证逻辑

  • 页面初始化时,组件 state 是独立的可修改对象,changeName 正常工作。
  • 提交到 Redux 时,传递的是拷贝后的对象,原组件 state 不会被冻结。
  • 后续调用 changeName 时,始终基于深拷贝的新对象修改,不会触碰只读属性。

内容的提问来源于stack exchange,提问作者user19539777

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 14:40:33