如何用Zod验证首次无默认选中的单选按钮组表单?
Zod + React Hook Form 单选按钮初始未选中与验证解决方案
问题场景
我有一个使用zod进行验证的单选按钮表单,代码如下:
import { useForm, useCallback } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import z from "zod"; const FormSchema = z.object({ options: z.enum(["option-0", "option-1", "option-2"], { required_error: "You must select an option", }) }) export default function Form() { const form = useForm<z.infer<typeof FormSchema>>({ resolver: zodResolver(FormSchema), defaultValues: { options: "", }, }) const onSubmit = useCallback(async (data: z.infer<typeof FormSchema>) => { console.log(data) }, []) return ( <form onSubmit={form.handleSubmit(onSubmit)}> {/* 单选按钮组 */} </form> ) }
这段代码无法正常运行,因为默认值""不在Zod枚举的可选值范围内。需要实现两个需求:
- 首次渲染时无单选按钮被选中
- 提交时通过Zod验证确保单选按钮值属于指定集合
解决方案
核心思路是:将字段初始值设为null(对应单选按钮未选中状态),同时调整Zod Schema,允许初始值为非枚举值,但强制提交时必须选择有效选项。
步骤1:调整Zod Schema
使用.nullable()允许字段初始值为null,再通过refine确保提交时字段不为null且属于枚举集合:
const FormSchema = z.object({ options: z.enum(["option-0", "option-1", "option-2"]) .nullable() .refine(val => val !== null, { message: "You must select an option", }) })
步骤2:配置React Hook Form
将默认值设为null,并设置验证模式为onSubmit(避免初始渲染就触发错误提示):
const form = useForm<z.infer<typeof FormSchema>>({ resolver: zodResolver(FormSchema), defaultValues: { options: null, // 初始未选中 }, mode: "onSubmit", // 仅提交时验证 })
步骤3:渲染单选按钮组
为每个枚举值生成单选按钮,绑定form.register:
<form onSubmit={form.handleSubmit(onSubmit)}> {["option-0", "option-1", "option-2"].map(option => ( <div key={option}> <input type="radio" id={option} name="options" value={option} {...form.register("options")} /> <label htmlFor={option}>{option}</label> </div> ))} {/* 错误提示 */} {form.formState.errors.options && ( <p style={{ color: "red" }}>{form.formState.errors.options.message}</p> )} <button type="submit">提交</button> </form>
效果说明
- 首次渲染时,所有单选按钮都未被选中(因为表单初始值为
null,无匹配的单选按钮value) - 提交时如果未选择任何选项,Zod会抛出"You must select an option"的错误
- 选中任一有效选项后,表单可正常提交,且提交数据符合枚举要求
内容的提问来源于stack exchange,提问作者sherrellbc
相关产品推荐
相关产品推荐

