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

React中如何使用useState钩子更新数组中的嵌套对象?

问题分析与解决方案

错误原因

你当前的更新代码存在结构错误:在修改form_values[0]时,错误地展开了整个prevStyle.form_values数组(而非数组内的第一个对象),导致form_values被替换成不符合原结构的对象,后续读取form_values[0]自然会报错。

修复单个字段的更新(临时方案)

将更新代码里的...prevStyle.form_values改成...prevStyle.form_values[0],即可正确修改第一个表单项的field_seq:

<Form.Control
  type="number"
  value={documentObj.form_values[0].field_seq}
  onChange={(event) => {
    setDocument((prevState) => ({
      ...prevState,
      form_values: [
        {
          ...prevState.form_values[0],
          field_seq: parseInt(event.target.value, 10), // 转成数字类型,匹配初始的null类型
        },
      ],
    }));
  }}
/>

通用状态更新函数(最终方案)

要处理所有嵌套层级的输入更新,包括顶层字段、form_values数组项、甚至select_values里的子项,可以实现通用的不可变更新逻辑:

1. 通用不可变更新工具函数

这个函数能根据传入的字段路径(比如['form_values', 0, 'field_name']),在不修改原状态的前提下更新指定字段:

const updateNestedState = (state, path, value) => {
  const [key, ...restPath] = path;
  if (restPath.length === 0) {
    // 到达最后一层,直接更新值
    if (Array.isArray(state)) {
      const newArray = [...state];
      newArray[key] = value;
      return newArray;
    }
    return { ...state, [key]: value };
  }
  // 递归处理嵌套层级
  if (Array.isArray(state)) {
    const newArray = [...state];
    newArray[key] = updateNestedState(newArray[key], restPath, value);
    return newArray;
  }
  return {
    ...state,
    [key]: updateNestedState(state[key], restPath, value),
  };
};

2. 通用输入变更处理器

基于上面的工具函数,实现一个通用的处理器,可通过参数指定要更新的字段路径:

const handleInputChange = (path) => (event) => {
  let { value } = event.target;
  // 根据字段类型做类型转换,匹配初始状态的类型定义
  if (path.includes('field_seq')) {
    value = value === '' ? null : parseInt(value, 10);
  } else if (path.includes('is_mandatory') || path.includes('value')) {
    value = value === 'true';
  }
  setDocument(prevState => updateNestedState(prevState, path, value));
};

3. 使用通用处理器的示例

现在不管是顶层字段还是嵌套字段,都可以用这个函数统一处理:

{/* 更新顶层的document_name */}
<Form.Control
  type="text"
  value={documentObj.document_name}
  onChange={handleInputChange(['document_name'])}
/>

{/* 更新form_values[0]的field_seq */}
<Form.Control
  type="number"
  value={documentObj.form_values[0].field_seq ?? ''} // 处理null值,避免输入框显示null
  onChange={handleInputChange(['form_values', 0, 'field_seq'])}
/>

{/* 更新form_values[0]的is_mandatory(复选框示例) */}
<Form.Check
  type="checkbox"
  checked={documentObj.form_values[0].is_mandatory}
  onChange={(e) => handleInputChange(['form_values', 0, 'is_mandatory'])({ target: { value: e.target.checked } })}
/>

{/* 更新form_values[0].select_values[0]的label */}
<Form.Control
  type="text"
  value={documentObj.form_values[0].select_values[0].label}
  onChange={handleInputChange(['form_values', 0, 'select_values', 0, 'label'])}
/>

补充说明

  • 类型转换逻辑可根据你的实际字段需求调整,确保状态类型与初始定义一致;
  • 如果form_values是动态生成的数组(不止一个项),遍历数组时可将index作为路径参数传入,比如['form_values', index, 'field_name']。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:15:27