如何在Zod与react-hook-form中为数字类型设置非零默认值?
如何将价格输入的默认值设为空值而非0(Zod + react-hook-form)
要实现价格输入初始为空且避免非受控错误,需要同时调整Zod校验规则、react-hook-form的默认值以及表单输入组件的处理逻辑,具体步骤如下:
1. 修改Zod Schema,支持空输入并保留正数校验
原Schema要求price必须是正数,但空输入(空字符串或null)需要被允许作为初始状态,同时提交时必须验证为有效正数。可以通过transform处理空值转换,再用refine做最终校验:
import * as z from "zod"; export const ProductSchema = z.object({ title: z.string().min(2), price: z.union([z.string().optional(), z.number()]) // 将空字符串或null转为null,其他值转为数字 .transform(val => val === "" || val == null ? null : Number(val)) // 提交时验证必须是非空正数 .refine(val => val !== null && val > 0, "Price must be a positive number"), discount: z.number().int().min(0).max(100), // ...其他字段 }) export type ProductType = z.infer<typeof ProductSchema>;
也可以用更简洁的coerce方式,自动将输入转为数字(空字符串会被转为NaN,后续通过refine排除):
price: z.coerce.number() .nullable() .refine(val => val !== null && val > 0, "Price must be a positive number"),
2. 更新react-hook-form的defaultValues
将price的默认值设为null,确保初始状态有明确的受控值,避免非受控输入错误:
const form = useForm<ProductType>({ resolver: zodResolver(ProductSchema), defaultValues: { title: "", price: null, // 替换原有的0 discount: 0, // ...其他字段 }, });
3. 调整Input组件的value显示
由于number类型的输入框会把null显示为文本"null",需要将null转为空字符串,保证输入框初始为空:
<FormField control={control} render={({ field }) => ( <FormItem> <FormLabel>Price</FormLabel> <Input {...field} value={field.value ?? ""} // 关键:将null转换为空字符串 disabled={isPending} placeholder="Price of product" type="number" className="shadow-sm focus:ring-primary-500 focus:border-primary-500 sm:text-sm border-gray-300 rounded-md bg-white" /> <FormMessage>{errors.price?.message}</FormMessage> </FormItem> )} name="price" />
这样设置后,输入框初始为空,符合需求;同时react-hook-form保持受控状态,Zod会在提交时校验价格必须为正数,空输入会触发对应的错误提示。
内容的提问来源于stack exchange,提问作者Apollo Vostok
相关产品推荐
相关产品推荐

