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
相关产品推荐
相关产品推荐

