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

React Hook Form提交验证:如何等待错误状态更新?

解决React Hook Form提交时验证状态未及时更新的问题

核心原因

你遇到的问题本质是validate/trigger属于异步操作,调用后立即读取formState.errors时,状态还未完成更新,导致拿到空对象。下面是几种直接有效的解决方式:


方案1:用handleSubmit自带的验证流程(推荐)

React Hook Form的handleSubmit会自动先执行所有验证(字段级+提交时自定义验证),只有验证完全通过才会进入你的提交逻辑,无需手动调用validate或读取errors。

示例代码:

import { useForm } from 'react-hook-form';

function YourModalForm() {
  const { register, handleSubmit, formState: { errors }, setError } = useForm();

  const onValidSubmit = async (formData) => {
    // 这里的formData已经是验证通过后的合法数据
    // 执行你的mutation逻辑
    await yourApiMutation(formData);
    // 关闭模态框
    closeModal();
  };

  // 如果需要额外的提交时自定义验证(比如异步校验)
  const onSubmit = async (formData) => {
    // 示例:异步检查用户名是否重复
    const isDuplicate = await checkUsernameUnique(formData.username);
    if (isDuplicate) {
      setError('username', { message: '该用户名已存在' });
      return; // 终止后续提交流程
    }
    // 验证通过,执行提交
    await onValidSubmit(formData);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input 
        {...register('username', { required: '用户名不能为空' })} 
        placeholder="用户名"
      />
      {errors.username && <span className="error">{errors.username.message}</span>}
      
      <button type="submit">保存</button>
    </form>
  );
}

方案2:手动调用trigger并等待异步结果

如果必须手动触发验证而非用handleSubmit,可以使用trigger方法——它会返回一个布尔值表示验证是否通过,同时会更新errors状态,必须等待这个Promise完成后再判断。

示例代码:

import { useForm } from 'react-hook-form';

function YourModalForm() {
  const { register, trigger, formState: { errors } } = useForm();

  const onSave = async () => {
    // 触发所有字段的验证,等待异步操作完成
    const isAllValid = await trigger();
    
    // 此时errors已更新,可直接判断
    if (isAllValid && Object.keys(errors).length === 0) {
      const formData = getValues(); // 获取表单数据
      await yourApiMutation(formData);
      closeModal();
    }
  };

  return (
    <div>
      <input {...register('email', { required: '邮箱不能为空', pattern: { value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: '邮箱格式不正确' } })} />
      {errors.email && <span className="error">{errors.email.message}</span>}
      
      <button onClick={onSave}>保存</button>
    </div>
  );
}

trigger也可以单独验证某个字段,比如trigger('email')只校验邮箱字段。


方案3:监听errors状态变化(特殊场景用)

如果因为业务逻辑限制必须依赖errors状态变化,可以用useEffect监听,但这种方式不如前两种直接,仅作备选:

import { useForm } from 'react-hook-form';
import { useEffect, useRef } from 'react';

function YourModalForm() {
  const { register, trigger, formState: { errors } } = useForm();
  const isSubmitting = useRef(false); // 标记是否正在提交

  const onSave = () => {
    isSubmitting.current = true;
    trigger(); // 触发验证
  };

  useEffect(() => {
    if (isSubmitting.current) {
      isSubmitting.current = false;
      // 验证通过则执行提交
      if (Object.keys(errors).length === 0) {
        const formData = getValues();
        yourApiMutation(formData).then(() => closeModal());
      }
    }
  }, [errors]);

  // 表单渲染逻辑...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 09:06:05