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

React中如何获取动态创建输入框的数据?

问题解决

你的代码存在三个核心问题,直接导致了输入时字段消失、只能获取第一组数据的现象:

  1. 更新练习数组时丢失其他项:handle函数里更新exercises时,直接把数组替换成只包含当前修改项的新数组,其他已添加的练习项全被清空,所以输入新字符后新增字段就消失了。
  2. 输入框未绑定状态值:输入框没有和状态数据绑定,属于非受控组件,状态更新后无法同步显示正确内容,引发异常渲染。
  3. 用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 12:31:01