React Hook Form密码显示/隐藏首次点击失效问题求助
问题解决思路及方案
问题根源
你遇到的问题核心在于表单校验模式onBlur的触发逻辑:当点击眼睛按钮时,密码输入框会失去焦点,触发onBlur校验,而状态isPasswordVisible的更新和输入框的type属性变化,会因焦点转移导致的校验触发产生渲染顺序冲突,最终造成首次点击时功能失效,第二次点击才正常。
解决方案
方案1:阻止按钮触发输入框失焦(推荐)
给眼睛按钮添加属性,让点击它时输入框不会失去焦点,从而避免触发不必要的onBlur校验,同时保证状态更新后输入框type立即生效:
<div className="form-field-wrapper input-password"> <Input field type={isPasswordVisible ? 'text' : 'password'} name="password" label={<Translate>auth.signup.signup-form-section.password</Translate>} /> <button type="button" onClick={() => setIsPasswordVisible(!isPasswordVisible)} className="show-password-icon" tabIndex="-1" onMouseDown={(e) => e.preventDefault()} > <Icon src={`${RESOURCE_URL}${isPasswordVisible ? '/eye.svg' : '/eye_close.svg'}`} height={24} width={24} /> </button> </div>
tabIndex="-1":让按钮无法通过键盘聚焦,避免干扰输入框焦点状态onMouseDown={(e) => e.preventDefault()}:阻止点击按钮时的默认行为,防止输入框失去焦点
方案2:调整表单校验触发时机
如果业务允许,可以修改react-hook-form的校验模式,避免输入框失焦时立即校验:
const formMethods = useForm({ mode: 'onSubmit', resolver: yupResolver(schema), defaultValues });
- 改为
onSubmit模式后,校验只会在提交表单时触发,彻底避免此类焦点相关的校验冲突
方案3:确保自定义Input组件响应属性变化
如果你的Input是自定义组件且使用了React.memo或类组件,需确保它能正确响应type属性的变化:
const Input = React.memo(({ field, type, ...props }) => { // 你的组件逻辑 }, (prevProps, nextProps) => { // 当type变化时强制重新渲染 if (prevProps.type !== nextProps.type) return false; // 其他属性的比较逻辑 });
内容的提问来源于stack exchange,提问作者Priyen Mehta
相关产品推荐
相关产品推荐

