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

如何用React表单数据更新useState中的嵌套对象状态?

解决React嵌套对象状态更新问题

问题原因

你的onInputChange函数仅能处理顶层字段(如firstName、lastName),对于嵌套在adres里的street和city,直接用{...user, [e.target.name]: e.target.value}会在user根对象下新增独立的street和city属性,而非更新adres内部的对应字段。另外,你对嵌套字段的解构写法错误,表单也缺失地址相关的输入框。

修复方案

1. 修正状态更新函数

修改onInputChange,区分顶层字段与嵌套字段,正确更新adres对象:

const onInputChange = (e) => {
  const { name, value } = e.target;
  // 处理adres下的嵌套字段
  if (name === 'street' || name === 'city') {
    setUser(prevUser => ({
      ...prevUser,
      adres: {
        ...prevUser.adres, // 保留adres原有字段
        [name]: value // 更新目标字段
      }
    }));
  } else {
    // 处理顶层字段
    setUser(prevUser => ({
      ...prevUser,
      [name]: value
    }));
  }
};

2. 修正字段解构

从adres对象中正确提取street和city:

const { firstName, lastName, adres: { street, city } } = user;

3. 添加地址输入框

在表单中补充street和city的输入组件:

<div className="mb-3">
  <label htmlFor="Street" className="form-label">
    Street
  </label>
  <input
    type="text"
    className="form-control"
    placeholder="Enter your street"
    name="street"
    value={street}
    onChange={(e) => onInputChange(e)}
    required
  />
</div>
<div className="mb-3">
  <label htmlFor="City" className="form-label">
    City
  </label>
  <input
    type="text"
    className="form-control"
    placeholder="Enter your city"
    name="city"
    value={city}
    onChange={(e) => onInputChange(e)}
    required
  />
</div>

完整修改后的组件代码

import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import axios from "axios";

export default function AddUser() {
  let navigate = useNavigate();

  const [user, setUser] = useState({
    firstName: "",
    lastName: "",
    adres: {
      street: "",
      city: "",
    }
  });

  const onInputChange = (e) => {
    const { name, value } = e.target;
    if (name === 'street' || name === 'city') {
      setUser(prevUser => ({
        ...prevUser,
        adres: {
          ...prevUser.adres,
          [name]: value
        }
      }));
    } else {
      setUser(prevUser => ({
        ...prevUser,
        [name]: value
      }));
    }
  };

  const onSubmit = async (e) => {
    e.preventDefault();
    await axios.post("http://localhost:8080/registration/registerUser", user);
    navigate("/");
  };

  const { firstName, lastName, adres: { street, city } } = user;

  return (
    <div className="container">
      <div className="row">
        <div className="col-md-6 offset-md-3 border rounded p-4 mt-2 shadow">
          <h2 className="text-center m-4">Register User</h2>
          <form onSubmit={(e) => onSubmit(e)}>
            <div className="mb-3">
              <label htmlFor="Firstname" className="form-label">
                First Name
              </label>
              <input
                type="text"
                className="form-control"
                placeholder="Enter your name"
                name="firstName"
                value={firstName}
                onChange={(e) => onInputChange(e)}
                required
              />
            </div>
            <div className="mb-3">
              <label htmlFor="Lastname" className="form-label">
                Last Name
              </label>
              <input
                type="text"
                className="form-control"
                placeholder="Enter your lastname"
                name="lastName"
                value={lastName}
                onChange={(e) => onInputChange(e)}
                required
              />
            </div>
            <div className="mb-3">
              <label htmlFor="Street" className="form-label">
                Street
              </label>
              <input
                type="text"
                className="form-control"
                placeholder="Enter your street"
                name="street"
                value={street}
                onChange={(e) => onInputChange(e)}
                required
              />
            </div>
            <div className="mb-3">
              <label htmlFor="City" className="form-label">
                City
              </label>
              <input
                type="text"
                className="form-control"
                placeholder="Enter your city"
                name="city"
                value={city}
                onChange={(e) => onInputChange(e)}
                required
              />
            </div>
            <button type="submit" className="btn btn-outline-primary">
              Submit
            </button>
            <Link type="submit" className="btn btn-danger mx-2" to="/">
              Cancel
            </Link>
          </form>
        </div>
      </div>
    </div>
  );
}

关键说明

  • 使用函数式更新setUser(prevUser => ...)确保每次更新都基于最新状态,避免旧状态覆盖问题。
  • 更新嵌套对象时,需先展开上层对象(...prevUser.adres)再修改目标字段,防止丢失其他嵌套属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 07:25:40