使用react-hook-form与zod构建的表单测试失败问题排查
问题解决:React Hook Form + Zod 表单校验测试不显示错误提示
问题原因
你的Zod校验规则存在核心问题:
z.string()默认允许空字符串,提交空密码时Zod不会判定为错误,因此不会渲染对应的alert提示- 邮箱字段的
z.string().email()会拒绝空字符串(空串不符合邮箱格式),但密码字段无空值限制,导致测试期望的2个alert元素无法全部出现
修复步骤
1. 更新Zod校验Schema
修改表单校验规则,给两个字段添加nonempty()约束,确保空值被判定为无效:
import { zodResolver } from '@hookform/resolvers/zod' import { useForm } from 'react-hook-form' import { z } from 'zod' // 修改后的Schema,添加nonempty限制 const formSchema = z.object({ email: z.string().nonempty('邮箱不能为空').email('请输入有效的邮箱地址'), password: z.string().nonempty('密码不能为空'), }) type Input = z.infer<typeof formSchema> export function SimpleForm() { const { register, handleSubmit, formState: { errors }, } = useForm<Input>({ resolver: zodResolver(formSchema) }) function onSubmit() {} return ( <form onSubmit={handleSubmit(onSubmit)}> <label htmlFor='email'>email</label> <input id='email' {...register('email')} type='email' /> {errors.email && <span role='alert'>{errors.email.message}</span>} <label htmlFor='password'>password</label> <input id='password' {...register('password')} type='password' /> {errors.password && <span role='alert'>{errors.password.message}</span>} <button type='submit'>SUBMIT</button> </form> ) }
2. 测试代码无需修改
你的测试逻辑是正确的,修改Schema后,提交空表单时两个字段都会触发校验错误,渲染对应的alert元素,screen.findAllByRole('alert')会找到2个元素,测试即可通过。
补充说明
- Zod的
z.string()仅校验值类型为字符串,空字符串""属于合法字符串,不会触发错误 nonempty()方法强制要求字符串长度至少为1,是处理必填字段空值校验的标准方式- React Hook Form的
handleSubmit会在提交时自动触发Zod resolver的校验,校验失败后更新formState.errors,从而渲染错误提示
内容的提问来源于stack exchange,提问作者TunA
相关产品推荐
相关产品推荐

