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

React Hook Form调用trigger()后首次无法读取errors对象的解决方法

解决React Hook Form中trigger()首次无法读取errors的问题

核心原因

trigger()是异步方法,它触发表单验证后,React Hook Form需要等待验证完成才会更新formState.errors对象。如果在调用trigger()后同步读取errors,拿到的还是更新前的旧值(空对象),这就是你首次点击提交时控制台打印空对象的原因。

可靠解决方案

方案1:await trigger(),等待验证完成后处理errors

直接等待trigger()执行完毕,此时errors已经更新为最新状态,可直接读取并处理:

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

function App() {
  const { register, trigger, formState: { errors } } = useForm({
    defaultValues: { email: "", password: "" }
  });

  const handleSubmit = async () => {
    // 等待验证完成
    const isFormValid = await trigger();
    
    if (!isFormValid) {
      // 此时errors已更新,可直接读取
      console.log(errors);
      
      // 聚焦第一个错误字段
      const firstErrorField = Object.keys(errors)[0];
      if (firstErrorField) {
        // 通过register获取对应字段的ref并聚焦
        const fieldRef = register(firstErrorField).ref;
        fieldRef.current?.focus();
      }
    }
  };

  return (
    <div>
      <input {...register("email", { required: "Email is required" })} placeholder="Email" />
      {errors.email && <p>{errors.email.message}</p>}
      
      <input {...register("password", { required: "Password is required" })} placeholder="Password" type="password" />
      {errors.password && <p>{errors.password.message}</p>}
      
      <button onClick={handleSubmit}>Submit</button>
    </div>
  );
}

export default App;

方案2:监听errors变化,自动执行后续逻辑

如果需要在errors更新后自动处理(比如自动聚焦错误字段),可以用useEffect监听errors的变化:

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

function App() {
  const { register, trigger, formState: { errors } } = useForm({
    defaultValues: { email: "", password: "" }
  });

  // 存储字段ref,方便快速获取
  const fieldRefs = {
    email: register("email").ref,
    password: register("password").ref
  };

  // 监听errors变化,自动聚焦第一个错误字段
  useEffect(() => {
    const errorFields = Object.keys(errors);
    if (errorFields.length > 0) {
      const firstField = errorFields[0];
      fieldRefs[firstField].current?.focus();
    }
  }, [errors]);

  const handleSubmit = async () => {
    await trigger();
  };

  return (
    <div>
      <input {...register("email", { required: "Email is required" })} placeholder="Email" />
      {errors.email && <p>{errors.email.message}</p>}
      
      <input {...register("password", { required: "Password is required" })} placeholder="Password" type="password" />
      {errors.password && <p>{errors.password.message}</p>}
      
      <button onClick={handleSubmit}>Submit</button>
    </div>
  );
}

export default App;

为什么设置Timeout没用?

硬设Timeout不可靠,因为React的渲染周期和验证完成的时间不确定——Timeout太短会赶不上状态更新,太长又会导致不必要的延迟。用await trigger()或useEffect监听状态变化,是基于React Hook Form的状态更新机制,更稳定可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:20:51