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

React修改嵌套对象数组状态时出现Cannot read properties of undefined错误

问题描述

尝试修改名为configure的嵌套数组状态时,触发错误:Cannot read properties of undefined (reading 'map')。场景是通过以下代码向指定分区的字段数组添加元素:

const [tabValue, setTabValue] = useState(0);
const [configure, setConfigure] = useState(config);

const addField = (name: string, value: any, type: string) => {
  const newItem = {
    _id: uuidv4(),
    name,
    value,
    type
  }
  const newArr = [...configure.sections[tabValue].fields, newItem]

  setConfigure((prevState: any) => ({
    ...prevState.sections[tabValue],
    fields: newArr
  }));

  console.log(configure)
}

其中tabValue代表当前操作的分区索引。渲染时的以下代码触发了上述错误:

return (
  <div className="App">
    <SearchForm handleUpdateSearch={handleUpdateSearch} />
    <CreateForm
      onAdd={addField} />
    <TabList
      tabValue={tabValue}
      setTabValue={setTabValue}
      configure={configure}
      setConfigure={setConfigure}
    />
    {configure.sections.map((s: any, i: any) => {
      return (
        <>
          {tabValue === i && <Section
            {...s}
            configure={configure}
            setConfigure={setConfigure}
            tabValue={tabValue}
          />}
        </>
      )
    })}

  </div>
); 

已知configure是包含sections数组的对象,每个section项包含fields数组(嵌套结构)。

问题分析

你判断的没错,问题出在状态更新时的对象展开逻辑错误:

  • 原代码中setConfigure的回调只返回了prevState.sections[tabValue]的展开结果+修改后的fields,这相当于把整个configure状态替换成了单个section对象,而非完整的原结构。
  • 新状态里不再有sections属性,所以渲染时configure.sections会变成undefined,调用map时就触发了报错。
解决方案

需要完整保留configure的原有结构,只修改目标分区的fields数组,正确的状态更新逻辑如下:

方案一:分步复制修改

const addField = (name: string, value: any, type: string) => {
  const newItem = {
    _id: uuidv4(),
    name,
    value,
    type
  };

  setConfigure((prevState: any) => {
    // 1. 复制原sections数组,避免直接修改原状态
    const updatedSections = [...prevState.sections];
    // 2. 复制目标分区对象,修改其fields数组
    const updatedSection = {
      ...updatedSections[tabValue],
      fields: [...updatedSections[tabValue].fields, newItem]
    };
    // 3. 替换sections数组中的目标分区
    updatedSections[tabValue] = updatedSection;
    // 4. 返回完整的configure新状态
    return {
      ...prevState,
      sections: updatedSections
    };
  });
};

方案二:用数组map简化写法

const addField = (name: string, value: any, type: string) => {
  const newItem = {
    _id: uuidv4(),
    name,
    value,
    type
  };

  setConfigure((prevState: any) => ({
    ...prevState,
    sections: prevState.sections.map((section: any, index: number) => {
      if (index === tabValue) {
        return {
          ...section,
          fields: [...section.fields, newItem]
        };
      }
      return section;
    })
  }));
};

另外注意:console.log(configure)无法看到更新后的状态(因为setState是异步的),如果要验证更新结果,可以在setConfigure的回调里打印,或者用useEffect监听configure的变化。

内容的提问来源于stack exchange,提问作者Богдан Шевченко

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 20:06:33