react-hook-form中useRef与直接使用watch函数的差异
React Hook Form 中两种确认密码验证方式的区别
我来拆解这两种实现的核心差异,结合实际场景帮你判断哪种更适合:
1. 重渲染行为差异
- 直接调用
watch('password'):watch是 React Hook Form 提供的响应式订阅方法,当password字段的值变化时,组件会因为依赖的password变量更新而触发重渲染。也就是说,用户每输入一个密码字符,整个表单组件都会重新渲染一次。 - 用
useRef存储密码值:useRef的current属性变化不会触发组件重渲染。只有当确认密码字段本身被修改、或者表单触发验证时,才会读取passwordRef.current的最新值,组件不会因为密码的变化而额外重渲染。
2. 验证实时性差异
- 直接
watch:能实时同步密码的变化。比如用户先输入密码,再输入确认密码后,后续修改密码时,确认密码的错误提示会立即更新(比如之前匹配,现在不匹配了,会马上显示错误)。 useRef方式:只有在确认密码字段被输入、或者表单提交时,才会验证是否和密码一致。如果用户改了密码但没碰确认密码,确认密码的错误状态不会自动更新,除非手动触发验证(比如调用trigger('confirmPassword'))。
3. 代码复杂度与性能
- 直接
watch:代码更简洁,不需要额外的useEffect来同步useRef的值,上手成本低。但如果表单组件比较复杂,频繁的重渲染可能会带来轻微的性能损耗。 useRef方式:需要额外通过useEffect订阅watch的变化来更新ref,代码多了几步,但能减少不必要的重渲染,性能更优,适合大型表单场景。
代码示例对比
方式一:useRef 存储密码值
import { useForm, watch } from 'react-hook-form'; import { useRef, useEffect } from 'react'; function RegisterForm() { const { register, formState: { errors } } = useForm(); const passwordRef = useRef(''); useEffect(() => { const unsubscribe = watch((values) => { passwordRef.current = values.password; }); return unsubscribe; }, [watch]); return ( <form> <input {...register('password', { required: '密码不能为空' })} type="password" placeholder="设置密码" /> <input {...register('confirmPassword', { required: '请再次输入密码', validate: val => val === passwordRef.current || '两次输入的密码不一致' })} type="password" placeholder="确认密码" /> {errors.confirmPassword && <span className="error">{errors.confirmPassword.message}</span>} </form> ); }
方式二:直接在 validate 中调用 watch
import { useForm, watch } from 'react-hook-form'; function RegisterForm() { const { register, formState: { errors } } = useForm(); const password = watch('password'); return ( <form> <input {...register('password', { required: '密码不能为空' })} type="password" placeholder="设置密码" /> <input {...register('confirmPassword', { required: '请再次输入密码', validate: val => val === password || '两次输入的密码不一致' })} type="password" placeholder="确认密码" /> {errors.confirmPassword && <span className="error">{errors.confirmPassword.message}</span>} </form> ); }
选择建议
- 如果你需要实时反馈密码匹配状态,且表单组件不大,优先用直接
watch的方式,代码更简洁。 - 如果你在意组件性能,或者只需要在确认密码输入/表单提交时验证,就用
useRef的方式,减少不必要的重渲染。
内容的提问来源于stack exchange,提问作者ghshin
相关产品推荐
相关产品推荐

