react-hook-form结合zod时提交按钮无响应问题排查
排查React Hook Form + Zod 登录表单提交无响应问题
核心问题本质
提交无响应且无控制台报错,但useForm返回的errors存在未处理错误,说明表单触发了校验失败但未暴露错误提示,同时Controller的字段绑定逻辑有问题,直接导致表单无法进入提交流程。
具体排查&修复步骤
1. 检查Controller与自定义组件的绑定是否完整
自定义FormField和PasswordField必须正确接收并绑定Controller传递的field属性(包含onChange、onBlur、value),否则字段值无法同步到表单状态,会触发隐性校验错误:
// 错误示例:自定义组件未绑定field核心属性 const FormField = ({ label, name }) => { return ( <div> <label>{label}</label> <input name={name} /> {/* 缺失onChange/onBlur/value绑定 */} </div> ); }; // 正确示例:Controller通过render传递field,自定义组件完整绑定 <Controller name="email" control={control} render={({ field }) => ( <FormField label="邮箱" {...field} /> )} /> // 自定义组件内部实现 const FormField = ({ label, onChange, onBlur, value }) => { return ( <div> <label>{label}</label> <input onChange={onChange} onBlur={onBlur} value={value} /> </div> ); };
2. 核对Zod校验规则与字段名的一致性
Zod Schema的字段key必须和Controller的name完全匹配,否则会触发未关联的校验错误:
// Zod Schema示例 const loginSchema = z.object({ email: z.string().email("请输入正确邮箱").nonempty("邮箱不能为空"), password: z.string().min(6, "密码至少6位").nonempty("密码不能为空"), }); // 注意:Controller的name必须严格对应schema中的key,比如不能把"email"写成"userEmail" <Controller name="email" control={control} ... />
3. 确认表单提交逻辑的绑定正确性
必须用handleSubmit包裹自定义提交函数,作为表单的onSubmit回调:
const { control, handleSubmit, errors } = useForm({ resolver: zodResolver(loginSchema), defaultValues: { email: "", password: "" }, }); // 错误示例:直接绑定提交函数,未用handleSubmit包裹 <form onSubmit={submitHandler}>...</form> // 正确示例:用handleSubmit包裹,确保校验通过后才执行提交逻辑 const onSubmit = (data) => { console.log("提交数据:", data); // 这里能打印说明校验通过 }; <form onSubmit={handleSubmit(onSubmit)}> {/* 字段组件 */} <button type="submit">登录</button> </form>
4. 手动触发校验,查看完整错误详情
可以在提交按钮点击时手动触发校验,明确错误来源:
const { trigger, errors } = useForm(...); const handleButtonClick = async () => { const isValid = await trigger(); console.log("校验结果:", isValid); console.log("错误详情:", errors); // 这里能看到具体哪个字段出错 }; <button type="submit" onClick={handleButtonClick}>登录</button>
5. 检查提交按钮的禁用逻辑
确认提交按钮的disabled属性没有被错误设置,比如错误判断表单状态:
const { formState: { isValid, isDirty } } = useForm(...); // 正确做法:结合isValid(校验通过)和isDirty(字段有修改)判断 <button type="submit" disabled={!isValid || !isDirty}>登录</button>
总结
最常见的问题是Controller与自定义组件的字段绑定不完整,导致表单值未同步,触发Zod校验失败却没有提示,看起来像提交无响应。优先检查自定义组件是否正确绑定field的onChange、onBlur、value属性,再核对Zod Schema的字段名与Controller的name是否完全匹配。
内容的提问来源于stack exchange,提问作者Bruno Bispo
相关产品推荐
相关产品推荐

