如何用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
相关产品推荐
相关产品推荐

