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

React中如何按ID向嵌套的inspections数组添加元素

问题:React useState 更新嵌套数组错误,新元素被添加到外层数组而非目标嵌套数组

我用React的useState Hook更新现有数组,想按ID找到对应元素,往它内部的inspections数组添加新检查项,但当前代码把新元素加到了data数组末尾,而非目标嵌套数组中。


初始数据

export const data = [
  {
    id: Math.floor(Math.random() * 999999),
    description: "",
    type: "car",
    inspections: [
      {
        id: Math.floor(Math.random() * 999999),
        name: `Inspection${Math.floor(Math.random() * 999999)}`,
        type: "any",
      },
    ],
  },
];

当前更新函数

const [dataArray, setDataArray] = useState(data);
const [inspection, setInspection] = useState("");

function handleInspection(id) {
  setDataArray((prevState) => [
    ...prevState,
    {
      id: id,
      description: "",
      type: "",
      inspections: [
        {
          id: Math.floor(Math.random() * 999999),
          name: `Inspection${Math.floor(Math.random() * 999999)}`,
          type: inspection,
        },
      ],
    },
  ]);
}

渲染与交互代码

{dataArray.map((vehicles) => {
  return (
    <div>
      <div key={vehicles.id}>vehicle type:{vehicles.type}</div>
      <ul>
        {vehicles.inspections.map((inspection) => {
          return <li>type: {inspection.type}</li>;
        })}
        lorry
        <input
          name="option"
          type="radio"
          className="form-control"
          autoFocus={true}
          onChange={() => setInspection("Lorry")}
          aria-label="Enter the title of your todo"
          placeholder="Enter a new todo"
          value={inspection}
        />
        van
        <input
          name="option"
          type="radio"
          className="form-control"
          onChange={() => setInspection("Van")}
          autoFocus={true}
          aria-label="Enter the title of your todo"
          placeholder="Enter a new todo"
          value={inspection}
        />
        car
        <input
          name="option"
          type="radio"
          className="form-control"
          onChange={() => setInspection("Car")}
          autoFocus={true}
          aria-label="Enter the title of your todo"
          placeholder="Enter a new todo"
          value={inspection}
        />
        any
        <input
          name="option"
          type="radio"
          className="form-control"
          onChange={() => setInspection("Any")}
          autoFocus={true}
          aria-label="Enter the title of your todo"
          placeholder="Enter a new todo"
          value={inspection}
        />
      </ul>
      <button
        className="addButton"
        onClick={() => handleInspection(vehicles.id)}
      >
        Add Inspection
      </button>
    </div>
  );
})}

问题原因与修正方案

问题根源

当前handleInspection函数只是把新对象直接追加到prevState数组末尾,完全没有定位到目标元素并更新其内部的inspections数组,这才导致新元素出现在外层数组。

修正后的更新函数

需要遍历数组找到对应ID的元素,复制该元素并更新其inspections数组,同时保留其他元素不变:

function handleInspection(id) {
  setDataArray((prevState) => 
    prevState.map(item => {
      // 匹配到目标元素时进行更新
      if (item.id === id) {
        return {
          ...item, // 复制原元素的所有属性
          inspections: [
            ...item.inspections, // 保留原有检查项
            {
              id: Math.floor(Math.random() * 999999),
              name: `Inspection${Math.floor(Math.random() * 999999)}`,
              type: inspection,
            }
          ]
        };
      }
      // 非目标元素直接返回原对象
      return item;
    })
  );
}

额外优化点

  1. 修复单选按钮的选中状态:每个单选按钮的value应设为对应类型值,同时通过checked属性关联inspection状态,确保选中状态正确显示:
// 以lorry选项为例,其余选项同理
<input
  name="option"
  type="radio"
  className="form-control"
  onChange={() => setInspection("Lorry")}
  aria-label="Select Lorry inspection type"
  value="Lorry"
  checked={inspection === "Lorry"}
/>
  1. 移除所有单选按钮的autoFocus属性,避免每次渲染自动聚焦影响用户操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:10:20