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

React Hook Form字段数组验证失效问题求助

React Hook Form Field Array 即时验证问题解决

问题说明

使用React Hook Form的useFieldArray时,为输入字段设置了required、minLength等验证规则,期望新增字段时立即触发验证,但实际添加空字段后,输入框的错误信息始终为undefined,无法通过onChange模式触发即时验证。

解决方案

1. 区分数组验证与字段验证

useFieldArray的rules配置是针对整个数组的验证(比如数组最小元素数量),单个输入字段的验证规则需要在useController中单独设置。

2. 新增字段后手动触发验证

onChange模式仅在字段值发生变化时触发验证,新增的空字段未触发onChange事件,因此需要在append操作完成后,手动调用trigger方法触发对应新字段的验证。

3. 完善错误信息展示

在受控输入组件中添加错误信息渲染逻辑,确保验证结果能直观呈现给用户。

修改后的代码示例

App组件

function App() {
  const { control, handleSubmit, trigger } = useForm({
    defaultValues: {
      test: [{ firstName: "Bill", lastName: "Luo" }]
    },
    mode: "onChange"
  });
  const { fields, append, remove } = useFieldArray({
    control,
    name: "test",
    // 此处rules用于验证数组本身(例:数组至少保留1个条目)
    rules: {
      minLength: {
        value: 1,
        message: "至少需要一个表单条目"
      }
    }
  });

  const onSubmit = (data) => console.log("data", data);

  return (
    <FormProvider {...{ control, handleSubmit, trigger }}>
      <form onSubmit={handleSubmit(onSubmit)}>
        <h1>Field Array</h1>
        <ul>
          {fields.map((item, index) => {
            return (
              <li key={item.id}>
                <FormControlledInput name={`test.${index}.firstName`} />
                <FormControlledInput name={`test.${index}.lastName`} />
                <button type="button" onClick={() => remove(index)}>
                  Delete
                </button>
              </li>
            );
          })}
        </ul>
        <section>
          <button
            type="button"
            onClick={() => {
              const newIndex = fields.length;
              append({ firstName: "", lastName: "" });
              // 手动触发新字段的验证
              trigger(`test.${newIndex}.firstName`);
              trigger(`test.${newIndex}.lastName`);
            }}
          >
            append
          </button>
        </section>

        <input type="submit" />
      </form>
    </FormProvider>
  );
}

受控输入组件

export const FormControlledInput = ({ name }) => {
  const { control } = useFormContext();

  const { field, fieldState } = useController({
    name,
    control,
    rules: {
      required: {
        value: true,
        message: "此字段为必填项"
      },
      minLength: {
        value: 4,
        message: "长度至少为4个字符"
      }
    }
  });

  return (
    <div style={{ marginBottom: '8px' }}>
      <input {...field} />
      {fieldState.error && (
        <span style={{ color: 'red', fontSize: '12px' }}>
          {fieldState.error.message}
        </span>
      )}
    </div>
  );
};

关键说明

  • 调用trigger时,新字段的路径为test.[newIndex].firstName,其中newIndex等于append操作前的fields.length(因为append后数组长度会自动+1)。
  • 后续字段值发生变化时,onChange模式会自动触发验证并更新fieldState.error,无需额外操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 22:12:51