React Hook Form切换标签页时阻止onBlur触发并改为onChange模式
React Hook Form Controller 标签页切换触发onBlur问题解答
问题背景
使用react-hook-form的Controller组件时出现异常:未与自定义组件交互,仅切换浏览器标签页,组件的onBlur事件仍会触发。相关代码如下:
<Controller name={name} control={control} rules={ { validate: (value) => { if (rules.required) { if (value == "INVALID") return errorMessage; else if (!value) return rules.required; } if (rules.validate instanceof Function) { return rules.validate(value) } return true; } } } render={({ field }) => ( <CustomComponent value={field.value} onChange={(value) => { field.onChange(value); typeof onChange === 'function' && onChange(value) }} onBlur={(value) => { field.onBlur(value); typeof onBlur === 'function' && onBlur(value) }} disabled={disabled} placeholder={placeholder} label={label} {...rest} /> )} />
现象原因
这是浏览器原生行为导致的:当焦点所在的标签页失去焦点时,浏览器会自动给当前获焦元素派发blur事件——无论用户是否实际和该元素产生过交互。react-hook-form的Controller只是绑定了这个原生事件,因此会触发对应的回调逻辑。
改为onChange触发的解决方案
要将校验和事件触发模式从onBlur改为onChange,需做以下两处调整:
1. 给Controller添加mode属性
在Controller组件上明确设置mode="onChange",让react-hook-form的校验逻辑在值发生变化时触发,而非元素失去焦点时。
2. 调整onBlur事件绑定(按需处理)
- 若不需要保留任何blur相关逻辑:直接移除CustomComponent上的
onBlur属性; - 若需要保留自定义的onBlur回调,但不想触发react-hook-form的blur关联逻辑:去掉
field.onBlur(value)这一行,仅保留自定义回调。
修改后的代码示例:
<Controller name={name} control={control} // 开启onChange触发模式 mode="onChange" rules={ { validate: (value) => { if (rules.required) { if (value == "INVALID") return errorMessage; else if (!value) return rules.required; } if (rules.validate instanceof Function) { return rules.validate(value) } return true; } } } render={({ field }) => ( <CustomComponent value={field.value} onChange={(value) => { field.onChange(value); typeof onChange === 'function' && onChange(value) }} // 仅保留自定义onBlur逻辑,移除react-hook-form的field.onBlur调用 onBlur={(value) => { typeof onBlur === 'function' && onBlur(value) }} disabled={disabled} placeholder={placeholder} label={label} {...rest} /> )} />
通过上述调整,标签页切换时不会再触发react-hook-form的校验逻辑,仅当组件值发生变化时才会触发对应处理。
内容的提问来源于stack exchange,提问作者Aman Verma
相关产品推荐
相关产品推荐

