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

React Hooks:如何使用useState更新包含数组的嵌套对象状态

问题根因

你遇到的只读报错来自三个核心问题:

  • 从Redux/RTK接口返回的原始数据默认是不可变(immutable)结构,直接修改原始对象的嵌套属性会被底层限制拦截
  • 参数调用和使用顺序不匹配:调用updateAnswerTexts时传入的参数顺序是(event, prop, 选项key, i18n下标),但之前的实现里把下标和选项key的使用顺序搞反了
  • 仅做了顶层对象的浅拷贝,嵌套层级的对象/数组仍然引用原始的只读对象,修改时自然触发只读限制

正确实现方案

方案1:手动逐层做不可变更新

不需要引入额外依赖,每层嵌套结构都生成新的引用替换:

const updateAnswerTexts = (event, prop, optionKey, i18nIndex) => {
  const newVal = event.target.value;
  setAnswerData(prevState => {
    // 拷贝顶层状态对象
    const newState = {...prevState};
    // 拷贝当前要修改的答案选项对象
    const targetOption = {...newState[optionKey]};
    // 拷贝选项下的多语言文本数组
    const newI18nList = [...targetOption.textI18Ns];
    // 拷贝要修改的单条多语文本,更新目标字段
    const updatedI18nItem = {...newI18nList[i18nIndex], [prop]: newVal};
    // 逐层替换回新状态
    newI18nList[i18nIndex] = updatedI18nItem;
    targetOption.textI18Ns = newI18nList;
    newState[optionKey] = targetOption;
    return newState;
  })
}

方案2:用Immer简化嵌套更新

如果项目嵌套结构多,可以引入Immer库做不可变更新,不需要手动逐层拷贝:

  1. 先安装依赖:
npm install immer
  1. 修改更新逻辑:
import { produce } from 'immer';

const updateAnswerTexts = (event, prop, optionKey, i18nIndex) => {
  const newVal = event.target.value;
  setAnswerData(prev => 
    produce(prev, draft => {
      // 直接修改draft对象即可,Immer内部会处理不可变更新
      draft[optionKey].textI18Ns[i18nIndex][prop] = newVal;
    })
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 09:39:00