ReactJS中如何通过onChange向useState的对象数组添加指定结构数据
问题原因
- 你的状态初始值是数组,但每次输入字符都会往数组追加新对象,每输入1个字符就新增1条,自然会出现多条
user_name、mobile_number分散在不同元素的情况 - 手机号输入框的更新逻辑错误,你将整个旧
user数组二次展开后追加到新数组,导致出现嵌套数组的异常结构 - 输入框的
value绑定错误,user是数组类型,直接读取user.user_name/user.mobile_number必然返回undefined,输入框会变成非受控组件
正确实现
如果需要直接维护你要求的[{user_name:xxx, mobile_number:xxx}]结构,可以参考以下代码:
import { useState } from 'react'; function ContactForm() { // 初始值就设置为带两个字段的单元素数组 const [userList, setUserList] = useState([{ user_name: '', mobile_number: '' }]); const submitForm = () => { console.log(userList); }; return ( <div> <input type="text" placeholder="name" onChange={(e) => setUserList((prev) => { // 拷贝原数组,修改第一个元素的user_name const newList = [...prev]; newList[0] = { ...newList[0], user_name: e.target.value } return newList; }) } value={userList[0].user_name} /> <input type="text" placeholder="mobile" onChange={(e) => setUserList((prev) => { const newList = [...prev]; newList[0] = { ...newList[0], mobile_number: e.target.value } return newList; }) } value={userList[0].mobile_number} /> <button onClick={submitForm}>Submit</button> </div> ); }
更合理的实现方式是单独维护表单对象状态,提交时再组装为你需要的数组结构,避免不必要的数组操作:
import { useState } from 'react'; function ContactForm() { // 单独维护表单对象状态 const [formData, setFormData] = useState({ user_name: '', mobile_number: '' }); // 提交时再组装为你需要的数组结构 const submitForm = () => { const userList = [formData]; console.log(userList); }; return ( <div> <input type="text" placeholder="name" onChange={(e) => setFormData((prev) => ({ ...prev, user_name: e.target.value })) } value={formData.user_name} /> <input type="text" placeholder="mobile" onChange={(e) => setFormData((prev) => ({ ...prev, mobile_number: e.target.value })) } value={formData.mobile_number} /> <button onClick={submitForm}>Submit</button> </div> ); }
useState数组内对象的更新逻辑
- 不可变原则:React的状态更新要求返回全新的引用值,不能直接修改原状态的数组/对象,直接
push、splice修改原数组,或者直接修改原对象属性的操作都不会触发重渲染,还会导致状态异常。 - 数组内对象更新步骤:首先通过展开运算符
[...prev]拷贝原数组得到新数组,再找到要更新的对象,通过{...oldObj}拷贝这个对象,修改对应属性后替换到新数组的对应位置,最后把新数组返回给状态更新函数即可。 - 如果是追加新对象到数组,直接返回
[...prev, newObj]即可,不要嵌套展开整个旧数组导致结构异常。
内容的提问来源于stack exchange,提问作者Piyush Jiwane
相关产品推荐
相关产品推荐

