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

React中如何实现点击按钮新增带递增编号的表单字段?

我来帮你搞定这个需求!在React里实现动态新增带递增编号的表单字段组其实非常直观,核心思路就是用状态来追踪这些字段组,然后根据状态渲染对应元素就行。下面给你两种实现方案,从基础到进阶,你可以根据自己的场景选择:

基础实现(非受控组件)

如果只是需要快速生成字段,暂时不需要实时跟踪字段值,这个版本足够简单:

import { useState } from 'react';

function DynamicPartForm() {
  // 用数组存储每个字段组的编号,初始默认有1组(对应01)
  const [fieldGroupNumbers, setFieldGroupNumbers] = useState([1]);

  // 点击按钮新增字段组的逻辑
  const addNewFieldGroup = () => {
    // 计算新的编号:取当前最大编号+1
    const nextNumber = Math.max(...fieldGroupNumbers) + 1;
    setFieldGroupNumbers([...fieldGroupNumbers, nextNumber]);
  };

  return (
    <div className="form-container">
      {/* 遍历渲染所有字段组 */}
      {fieldGroupNumbers.map(number => {
        // 把编号格式化为两位数字,比如1→01、2→02
        const formattedNum = number.toString().padStart(2, '0');
        return (
          <div key={number} className="field-group" style={{ margin: '10px 0' }}>
            <select 
              id={`part_id_${formattedNum}`} 
              name={`part_id_${formattedNum}`}
            >
              <option value="1">top</option>
              <option value="2">middle</option>
              <option value="3">bottom</option>
              <option value="4">none</option>
            </select>
            <input 
              type="text" 
              id={`part_color_${formattedNum}`} 
              name={`part_color_${formattedNum}`}
              style={{ marginLeft: '8px' }}
              placeholder={`Color for part ${formattedNum}`}
            />
          </div>
        );
      })}

      {/* 新增按钮 */}
      <button onClick={addNewFieldGroup} style={{ marginTop: '15px' }}>
        Add New Part Group
      </button>
    </div>
  );
}

export default DynamicPartForm;

关键细节说明:

  • 用fieldGroupNumbers数组维护所有字段组的编号,状态更新时React会自动重新渲染组件
  • padStart(2, '0')用来保证编号是两位格式,完美匹配你需要的part_id_01、part_id_02命名规则
  • 每个动态生成的字段组必须加唯一的key属性,这里直接用编号作为key,简单可靠
进阶实现(受控组件,推荐)

如果后续需要处理表单提交、字段验证或者实时同步字段值,受控组件版本会更符合React的数据流理念:

import { useState } from 'react';

function ControlledDynamicForm() {
  // 每个字段组存储编号+对应的值,方便跟踪表单数据
  const [fieldGroups, setFieldGroups] = useState([
    { id: 1, partId: '', partColor: '' }
  ]);

  const addNewFieldGroup = () => {
    const nextId = Math.max(...fieldGroups.map(group => group.id)) + 1;
    setFieldGroups([...fieldGroups, { id: nextId, partId: '', partColor: '' }]);
  };

  // 统一处理字段值变化
  const handleFieldChange = (groupId, fieldName, value) => {
    setFieldGroups(prevGroups => 
      prevGroups.map(group => 
        group.id === groupId 
          ? { ...group, [fieldName]: value } 
          : group
      )
    );
  };

  // 表单提交示例:直接从state提取数据,不用操作DOM
  const handleSubmit = (e) => {
    e.preventDefault();
    // 转换为后端需要的格式:比如{ part_id_01: "1", part_color_01: "red", ... }
    const submitData = {};
    fieldGroups.forEach(group => {
      const formattedId = group.id.toString().padStart(2, '0');
      submitData[`part_id_${formattedId}`] = group.partId;
      submitData[`part_color_${formattedId}`] = group.partColor;
    });
    console.log('提交的数据:', submitData);
    // 这里可以发送API请求提交数据
  };

  return (
    <form onSubmit={handleSubmit} className="form-container">
      {fieldGroups.map(group => {
        const formattedId = group.id.toString().padStart(2, '0');
        return (
          <div key={group.id} className="field-group" style={{ margin: '10px 0' }}>
            <select 
              id={`part_id_${formattedId}`} 
              name={`part_id_${formattedId}`}
              value={group.partId}
              onChange={(e) => handleFieldChange(group.id, 'partId', e.target.value)}
            >
              <option value="">请选择部件</option>
              <option value="1">top</option>
              <option value="2">middle</option>
              <option value="3">bottom</option>
              <option value="4">none</option>
            </select>
            <input 
              type="text" 
              id={`part_color_${formattedId}`} 
              name={`part_color_${formattedId}`}
              value={group.partColor}
              onChange={(e) => handleFieldChange(group.id, 'partColor', e.target.value)}
              style={{ marginLeft: '8px' }}
              placeholder={`Color for part ${formattedId}`}
            />
          </div>
        );
      })}

      <button type="button" onClick={addNewFieldGroup} style={{ marginRight: '10px' }}>
        Add New Part Group
      </button>
      <button type="submit">Submit Form</button>
    </form>
  );
}

export default ControlledDynamicForm;

这个版本的优势:

  • 实时跟踪每个字段的值,不需要在提交时遍历DOM获取数据
  • 方便添加表单验证逻辑(比如检查颜色是否为空)
  • 数据完全由React状态管理,符合单向数据流原则

内容的提问来源于stack exchange,提问作者reddy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:26:35