React Hook Form与Zod:必填错误未显示却触发类型错误问题
解决React Hook Form + Zod表单验证中空值触发类型错误而非必填错误的问题
问题原因
当表单中age字段为空时,React Hook Form会将空字符串""传递给Zod进行验证。而Zod的z.number()会优先检查输入类型:空字符串属于string类型,不符合number要求,因此直接触发invalid_type_error,而非required_error——后者仅在字段**完全缺失(值为undefined或未传入)**时才会触发。
解决方案
通过Zod的preprocess方法,先将空字符串转换为undefined,让Zod识别为字段缺失,从而触发必填错误提示;同时支持将合法的数字字符串转换为数字类型,确保验证逻辑符合预期。
最终Schema代码
const Schema = z.object({ age: z.preprocess( (val) => { // 空字符串转为undefined,触发必填错误 if (val === "") return undefined; // 将字符串类型的数字转为number,兼容输入场景 return typeof val === "string" ? Number(val) : val; }, z.number({ required_error: "Required", invalid_type_error: "Invalid type", }) ), }); type SchemaType = z.infer<typeof Schema>; const form = useForm<SchemaType>({ resolver: zodResolver(Schema), // 可选:设置默认值为undefined,更贴合必填校验逻辑 defaultValues: { age: undefined, }, });
验证效果
- 当
age字段为空时:空字符串被转为undefined,Zod触发required_error,显示"Required"提示。 - 当输入非数字字符串(如
"abc"):转换后得到NaN,Zod识别为无效数字类型,触发invalid_type_error,显示"Invalid type"提示。 - 当输入数字(如
20)或数字字符串(如"20"):正常转换为数字类型,验证通过,且Schema.parse({ age: 20 })能无错误执行。
补充说明
如果你的输入框使用type="number",React Hook Form会自动将输入值转为数字类型(空值时为""),上述方案依然适用。若希望严格限制输入为数字类型,也可以在注册字段时添加type="number",进一步优化用户输入体验。
内容的提问来源于stack exchange,提问作者datnm.qti
相关产品推荐
相关产品推荐

