react-hook-form onBlur验证失效问题排查求助
React Hook Form + Zod: 首次失焦不触发验证的排查与解决
1. 确认表单模式配置
确保useForm的mode设置为onBlur,这是触发失焦验证的核心配置(默认模式为onSubmit,不会自动在失焦时验证):
import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; const schema = z.object({ email: z.string().email().or(z.literal('')) // 允许合法邮箱或空字符串 }); const { register, errors, trigger } = useForm({ mode: 'onBlur', // 关键配置 resolver: zodResolver(schema) });
如果单独给字段配置触发时机,需确保register的trigger选项正确:
<input {...register('email', { trigger: 'onBlur' })} />
2. 校验Zod Schema逻辑
检查邮箱字段的规则是否符合预期,避免因Schema定义错误导致验证未触发:
- 允许空字符串+合法邮箱:使用
z.string().email().or(z.literal(''))(若允许undefined而非空字符串,可改用z.string().email().optional()) - 排查是否存在
refine/superRefine逻辑,比如依赖其他字段的验证,首次失焦时其他字段未初始化可能导致验证跳过。
3. 确保字段注册事件未被覆盖
自定义输入组件或手动绑定事件时,必须保留register返回的onBlur事件,否则React Hook Form无法捕获失焦动作:
- 错误示例(覆盖了原生onBlur):
<input value={value} onChange={(e) => handleChange(e)} onBlur={() => { /* 自定义逻辑 */ }} />
- 正确写法(合并事件):
const { onBlur, onChange, name } = register('email'); <input name={name} onChange={(e) => { onChange(e); handleCustomChange(e); }} onBlur={(e) => { onBlur(e); // 必须调用register返回的onBlur handleCustomBlur(e); }} />
4. 排查自定义组件的状态同步问题
如果输入组件封装了Tooltip、溢出测量等逻辑,需确认:
- 组件是否正确传递
value和onChange,没有延迟更新表单值的情况 - 异步操作(如测量宽度的
setTimeout)是否干扰了React Hook Form的状态更新,导致验证时机滞后
5. 手动触发验证的正确方式
如果需要手动调用验证,注意trigger是异步函数,需等待执行完成:
const { trigger } = useForm(); // 在自定义onBlur中调用 const handleBlur = async () => { await trigger('email'); // 等待验证完成 };
使用setError时,确保字段名匹配,且没有被clearErrors意外清空:
const { setError } = useForm(); setError('email', { type: 'custom', message: '邮箱格式无效' });
6. 检查版本兼容性
旧版本的react-hook-form或@hookform/resolvers可能存在onBlur验证的bug,尝试升级到最新稳定版:
npm update react-hook-form @hookform/resolvers zod
内容的提问来源于stack exchange,提问作者Michal Tal-Socher
相关产品推荐
相关产品推荐

