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

如何在React中更新三层嵌套对象的State?

三层嵌套React State更新问题

我用React的useState维护一个三层嵌套的DentistPayload对象,尝试更新其中的mainAddress属性时失败,还收到了TypeScript类型错误。

类型定义

export interface DentistPayload {
  croNumber: string;
  person: PersonPayload;
}

export interface PersonPayload {
  fullName: string;
  birthdate: string;
  cpfNumber: string;
  telephoneNumber: string;
  emailAddress: string;
  address: AddressPayload;
}

export interface AddressPayload {
  mainAddress: string;
  numberAddress: string;
  neighborHood: string;
  complementInfo: string;
  zipCode: string;
}

初始数据

{
    "croNumber":"272727",
    "person": {
        "fullName": "John",
        "birthdate": "2000-02-27",
        "cpfNumber": "11408247910",
        "telephoneNumber": "47996034002",
        "emailAddress": "john@gmail.com",
        "address": {
            "mainAddress": "Rua Amoroso Costa",
            "numberAddress": "171",
            "neighborHood": "Jardim das Américas",
            "complementInfo": "Casa",
            "zipCode": "81530-150"
        }
    }
}

错误的更新代码

onChange={(e) => setFormDentist({ ...formDentist, person: { address: { ...formDentist.person.address, mainAddress: e.target.value } } })}

收到的类型错误

Type '{ address: { mainAddress: string; numberAddress: string; neighborHood: string; complementInfo: string; zipCode: string; }; }' is missing the following properties from type 'PersonPayload': fullName, birthdate, cpfNumber, telephoneNumber, emailAddress

State定义

const [formDentist, setFormDentist] = useState<DentistPayload>({} as DentistPayload)

请问正确的更新方式是什么?


错误原因

更新person字段时,你只保留了address属性,丢失了PersonPayload要求的fullName、birthdate等必填字段,TypeScript因此报错。React更新嵌套state时,必须逐层解构对象,保留所有未修改的属性,仅更新目标字段。

正确的更新写法

基础写法

逐层解构嵌套对象,确保所有原有属性都被保留:

onChange={(e) => {
  setFormDentist({
    ...formDentist,
    person: {
      // 保留person对象的全部原有属性
      ...formDentist.person,
      address: {
        // 保留address对象的全部原有属性
        ...formDentist.person.address,
        mainAddress: e.target.value
      }
    }
  })
}}

函数式更新(更安全)

如果state更新依赖于之前的state值,推荐使用函数式更新,避免闭包导致的旧state问题:

onChange={(e) => {
  setFormDentist(prevState => ({
    ...prevState,
    person: {
      ...prevState.person,
      address: {
        ...prevState.person.address,
        mainAddress: e.target.value
      }
    }
  }))
}}

封装通用更新函数(可选)

如果需要更新多个嵌套字段,可以封装一个通用函数简化重复代码:

const updateNestedField = (path: string[], value: string) => {
  setFormDentist(prevState => {
    const newState = {...prevState};
    let current = newState;
    for (let i = 0; i < path.length - 1; i++) {
      current[path[i]] = {...current[path[i]]};
      current = current[path[i]];
    }
    current[path[path.length - 1]] = value;
    return newState;
  });
};

// 使用示例:更新mainAddress
onChange={(e) => updateNestedField(['person', 'address', 'mainAddress'], e.target.value)}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:55:22