如何在React Hook Form v6的Controller中使用Yup校验实现onTouched触发报错
问题原因
你当前的错误只在提交时显示,核心是两个问题:
- 没有给输入组件绑定
onBlur事件,React Hook Form 的touched状态完全依赖onBlur触发,没有这个事件的话,RHF 不知道字段是否被用户聚焦过,onTouched模式的校验规则自然不会触发,只有提交时 RHF 会强制把所有字段标记为 touched 才会展示错误。 - 错误提示没有结合
touched状态判断,不符合你要的「失焦后才展示错误」的交互逻辑。
修正方案
直接修改封装的子组件Controller部分的代码即可:
// 修正后的Children组件 <Controller control={control} name={name} defaultValue="" // 取出onBlur方法和字段状态 render={({ field: { onChange, value, name, onBlur }, fieldState: { touched } }) => ( <> <NumberFormat className="form-control form-control-lg" type="text" format={format} id={name} value={value} onChange={onChange} // 绑定onBlur事件,触发touched状态更新 onBlur={onBlur} /> {/* 只有字段被失焦过且存在错误时,才展示提示 */} {touched && errors && <span className="text-danger">{errors.message}</span>} </> )} />
如果你不想从父组件传递errors参数,也可以直接用Controller返回的fieldState里的error,写法更简洁:
// 不需要父组件传errors的版本 <Controller control={control} name={name} defaultValue="" render={({ field: { onChange, value, name, onBlur }, fieldState: { touched, error } }) => ( <> <NumberFormat className="form-control form-control-lg" type="text" format={format} id={name} value={value} onChange={onChange} onBlur={onBlur} /> {touched && error && <span className="text-danger">{error.message}</span>} </> )} />
版本校验
确认你的依赖版本匹配:React Hook Form v6 对应的@hookform/resolvers版本为 1.x 系列,版本不匹配也可能导致校验触发时机异常。
内容的提问来源于stack exchange,提问作者B. Christophe
相关产品推荐
相关产品推荐

