React 输入框onChange每次键入就新增数组对象的问题如何解决
核心问题定位
原代码的onChange逻辑存在两处核心疏漏,直接导致输入时每敲一个字符就新增一个对象的异常:
- 没有对数组里已有的课程条目做属性更新,反而在每次输入触发时,把旧数组展开后追加一个全新的零散对象,完全没动一开始初始化的那个空课程对象(也就是数组索引为0的条目)
- 两个输入框的更新逻辑是完全割裂的,没有把课程名、课程等级两个字段合并写到同一个课程对象里,所以最后生成的对象要么只有course属性,要么只有level属性,和预期的结构完全不符
正确的数组更新逻辑
在React里修改状态数组中指定的对象时,必须先遍历原数组,找到需要更新的目标条目,通过展开运算符保留条目其他原有属性的前提下,修改对应字段的值,绝对不能直接把新对象拼接到旧数组后面。
如果当前只需要单条课程录入,就固定更新数组索引为0的条目;如果后续要支持动态添加多门课程,只需要给每个输入框绑定对应的课程条目索引即可。
修正后的完整代码
import { React, useState } from 'react'; // Bootstrap Component import Button from 'react-bootstrap/Button'; import { TextField } from '@material-ui/core'; const Profile = () => { const [newCourseObj, setNewCourseObj] = useState( [ { course: "", level: "" } ] ); // 补充缺失的表单提交处理函数 const handleSubmit = (e) => { e.preventDefault(); // 此处可添加提交接口调用逻辑 console.log('待提交的课程数据:', newCourseObj); } return ( <form autoComplete="off" noValidate className="form" onSubmit={handleSubmit}> {/* 课程名称输入框 */} <TextField type="text" value={newCourseObj[0].course} onChange={(e) => { setNewCourseObj(prev => // 遍历数组,仅更新对应索引的条目 prev.map((item, index) => { if (index === 0) { // 展开原有对象,仅修改course字段,不丢失其他属性 return { ...item, course: e.target.value } } return item; }) ); }} /> {/* 课程等级输入框 */} <TextField type="number" value={newCourseObj[0].level} onChange={(e) => { setNewCourseObj(prev => prev.map((item, index) => { if (index === 0) { return { ...item, level: e.target.value } } return item; }) ); }} /> <Button variant="light" type="submit" className="save"><span className="material-icons"> done </span></Button> <div>{JSON.stringify(newCourseObj, null, 2)}</div> </form> ); } export default Profile;
多课程录入扩展方案
如果需要支持动态添加多门课程,只需要新增一个“添加课程”按钮,点击时执行setNewCourseObj(prev => [...prev, {course: "", level: ""}])即可插入空课程条目,同时给每个输入框传入对应的索引值,在onChange逻辑里判断当前要更新的条目索引即可,不需要每次输入都生成新对象。
内容的提问来源于stack exchange,提问作者frustrated-dev
相关产品推荐
相关产品推荐

