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

React函数组件动态表单受控组件警告无类解决方案

函数组件完全可以解决这个问题,不需要使用类组件。

问题原因

你碰到的非受控组件警告核心来自两个问题:

  • 新增表单项时字段名拼写错误:初始表单项的描述字段为StepDisc,但addFields方法里新增的对象误写为StepDiscs(末尾多了个s),导致新加表单项的StepDisc属性值为undefined。React中如果input的value属性初始为undefined,会默认将组件识别为非受控组件,后续赋值时组件切换为受控状态,就会抛出对应警告。
  • 原代码状态更新时只浅拷贝了外层数组,直接修改了数组内部的原对象,不符合React状态不可变的要求,极端场景下会出现渲染不生效的问题。
修复后完整代码
import { useState } from 'react';

function DynamicForm() {
  const [formFields, setFormFields] = useState([
    { StepNo: '', StepDisc: '' },
  ])

  const handleFormChange = (event, index) => {
    const { name, value } = event.target;
    setFormFields(prev => prev.map((item, i) => {
      if (i === index) return { ...item, [name]: value }
      return item
    }))
  }

  const submit = (e) => {
    e.preventDefault();
    console.log(formFields)
  }

  const addFields = () => {
    // 修正字段名拼写,和初始字段保持一致
    const newField = {
      StepNo: '',
      StepDisc: ''
    }
    setFormFields(prev => [...prev, newField])
  }

  const removeFields = (removeIndex) => {
    setFormFields(prev => prev.filter((_, index) => index !== removeIndex))
  }

  return (
    <div className="">
      <form onSubmit={submit}>
        {formFields.map((form, index) => {
          return (
            <div key={index}>
              <input
                name='StepNo'
                placeholder='StepNo'
                onChange={event => handleFormChange(event, index)}
                value={form.StepNo}
              />
              <input
                name='StepDisc'
                placeholder='StepDisc'
                onChange={event => handleFormChange(event, index)}
                value={form.StepDisc}
              />
              <button type="button" onClick={() => removeFields(index)}>Remove</button>
            </div>
          )
        })}
      </form>
      <button type="button" onClick={addFields}>Add More..</button>
      <br />
      <button type="submit">Submit</button>
    </div>
  );
}

export default DynamicForm;
关键修复点说明
  • 修正了addFields中的字段拼写错误,保证所有表单项对象都完整包含StepNo和StepDisc字段,初始值为空字符串,从根源避免value为undefined导致的受控/非受控切换问题
  • 所有状态更新都遵循不可变原则:更新输入值、新增/删除字段时都不直接修改原状态,而是生成全新的状态值传递给更新方法,避免潜在渲染异常
  • 所有非提交按钮添加type="button"属性,避免表单内按钮默认触发表单提交的问题
  • 状态更新改用函数式写法,避免连续操作状态时拿到过期的状态快照
  • 额外兜底方案:如果后续业务存在动态增减字段、无法保证所有字段初始都存在的场景,可以给input的value加空值兜底,例如写成value={form.StepDisc ?? ''},就算对应字段未定义,value也始终为字符串类型,彻底杜绝这类非受控组件警告。
  • 补充优化:如果表单增删操作比较频繁,不建议用数组下标作为map渲染的key,可以给每个新增字段生成唯一id作为key,避免重渲染时的输入值错位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 12:36:20