React中如何获取动态创建输入框的数据?
问题解决
你的代码存在三个核心问题,直接导致了输入时字段消失、只能获取第一组数据的现象:
- 更新练习数组时丢失其他项:
handle函数里更新exercises时,直接把数组替换成只包含当前修改项的新数组,其他已添加的练习项全被清空,所以输入新字符后新增字段就消失了。 - 输入框未绑定状态值:输入框没有和状态数据绑定,属于非受控组件,状态更新后无法同步显示正确内容,引发异常渲染。
- 用index作为列表key:React列表渲染用index当key,数组元素增减时会复用错误的组件实例,导致奇怪的渲染问题。
下面是修正后的完整代码:
import { useState } from "react"; export default StackTest; function StackTest() { const [formData, setFormData] = useState({ title: "", date: "", // 给每个练习项添加唯一id,避免用index当key exercises: [{ id: 1, Exercise: "benchpress", Reps: "5", Sets: "5" }], }); // 用函数式更新确保获取最新状态,同时保留原数组所有项 const handleExerciseChange = (value, type, index) => { setFormData(prev => ({ ...prev, exercises: prev.exercises.map((item, idx) => { if (idx === index) { // 根据类型修改对应字段 switch(type) { case "E": return { ...item, Exercise: value }; case "R": return { ...item, Reps: value }; case "S": return { ...item, Sets: value }; default: return item; } } return item; }) })); }; const updateForm = (e) => { setFormData((currentFormData) => ({ ...currentFormData, [e.target.name]: e.target.value, })); }; const handleAddExercise = (e) => { e.preventDefault(); setFormData((currentFormData) => { // 生成新的唯一id,简单用数组长度+1实现,实际项目可使用uuid库 const newId = currentFormData.exercises.length + 1; return { ...currentFormData, exercises: [ ...currentFormData.exercises, { id: newId, Exercise: "benchpress", Reps: "5", Sets: "5" }, ], }; }); }; return ( <> <form action=""> <label htmlFor="title">title</label> <input type="text" id="title" name="title" value={formData.title} onChange={updateForm} /> <label htmlFor="date">date</label> <input type="text" id="date" name="date" value={formData.date} onChange={updateForm} /> {formData.exercises.map((exercise, index) => { // 使用练习项的唯一id作为key,避免index引发的渲染异常 return ( <div key={exercise.id}> <input placeholder="exercise" value={exercise.Exercise} onChange={(e) => handleExerciseChange(e.target.value, "E", index)} /> <input placeholder="reps" value={exercise.Reps} onChange={(e) => handleExerciseChange(e.target.value, "R", index)} /> <input placeholder="sets" value={exercise.Sets} onChange={(e) => handleExerciseChange(e.target.value, "S", index)} /> <button onClick={handleAddExercise}>Add Exercise</button> </div> ); })} </form> </> ); }
关键修改说明:
- 保留所有练习项:通过
map遍历原数组,仅修改对应索引的项,确保其他练习数据不会丢失。 - 受控组件绑定:每个输入框绑定对应状态字段,让输入内容和状态实时同步。
- 替换列表key:用练习项的唯一id替代index作为key,避免数组变动时的组件复用错误。
内容的提问来源于stack exchange,提问作者nalydj
相关产品推荐
相关产品推荐

