React Hook Form表单报错Cannot read properties of undefined (reading 'set')的解决方法
解决React Hook Form中「Cannot read properties of undefined (reading 'set')」错误
这个错误几乎都是由于表单对象未正确初始化,或访问了未定义的表单方法/属性导致的,结合你使用yup schema的场景,以下是针对性的排查和解决步骤:
1. 检查useForm初始化时的resolver配置
使用yup做验证时,必须通过yupResolver将schema传入useForm的配置项,若遗漏或配置错误,会导致内部表单状态未正确初始化,触发该错误。
正确示例:
import { useForm } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; import * as yup from 'yup'; // 定义yup验证schema const formSchema = yup.object().shape({ username: yup.string().required('用户名不能为空'), email: yup.string().email('邮箱格式错误').required('邮箱不能为空') }); function LoginForm() { // 正确初始化useForm,传入resolver const { register, handleSubmit, formState: { errors } } = useForm({ resolver: yupResolver(formSchema), // 关键:必须配置此项 defaultValues: { // 建议设置默认值,避免初始状态未定义 username: '', email: '' } }); const onSubmit = (data) => { console.log(data); }; return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...register('username')} /> {errors.username && <p>{errors.username.message}</p>} <input {...register('email')} /> {errors.email && <p>{errors.email.message}</p>} <button type="submit">提交</button> </form> ); }
2. 避免错误解构或未定义的表单方法
确保你正确解构了useForm返回的对象,比如不要把register拼写成regist这类错误名称;也不要在组件外部(比如useEffect的依赖项之外、全局作用域)调用register,此时表单对象可能还未初始化。
3. 嵌套组件中正确传递表单上下文
如果在子组件中使用表单方法,不要手动传递register等属性,而是通过FormProvider和useFormContext来共享表单上下文,避免传递过程中出现未定义的情况:
// 父组件 import { FormProvider, useForm } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; import * as yup from 'yup'; import ChildInput from './ChildInput'; const formSchema = yup.object().shape({ password: yup.string().min(6, '密码至少6位').required('密码不能为空') }); function ParentForm() { const formMethods = useForm({ resolver: yupResolver(formSchema), defaultValues: { password: '' } }); return ( <FormProvider {...formMethods}> <ChildInput /> </FormProvider> ); } // 子组件 import { useFormContext } from 'react-hook-form'; function ChildInput() { // 通过useFormContext获取正确的表单方法 const { register, formState: { errors } } = useFormContext(); return ( <div> <input type="password" {...register('password')} /> {errors.password && <p>{errors.password.message}</p>} </div> ); }
4. 检查版本兼容性
确保react-hook-form、@hookform/resolvers和yup的版本相互兼容,版本不匹配可能导致内部逻辑异常。可以执行以下命令更新到最新兼容版本:
npm install react-hook-form@latest @hookform/resolvers@latest yup@latest
5. 避免条件渲染中的未初始化调用
不要在条件渲染的分支中(比如{isVisible && <input {...register('field')} />})直接使用register,如果条件为false时组件未挂载,后续条件变为true时可能出现表单对象未完全初始化的情况。可以确保表单方法在组件渲染前已正确获取。
内容的提问来源于stack exchange,提问作者Ankan Chanda
相关产品推荐
相关产品推荐

