Next.js中React Hook Form表单字段的条件验证实现方法
解决方案
核心是利用Zod的when方法实现条件验证,结合React Hook Form的Zod解析器,就能根据addContext开关的状态动态控制context字段的验证规则。
1. 定义带条件验证的Zod Schema
import { z } from "zod"; const formSchema = z.object({ chart: z.instanceof(File, { message: "请上传Chart文件", }), addContext: z.boolean(), // 条件验证逻辑:开关开启时context必填,关闭时跳过验证 context: z.string().when("addContext", { is: true, then: (schema) => schema.min(1, "请填写上下文内容"), otherwise: (schema) => schema.optional(), }), });
2. 结合React Hook Form和shadcn/ui实现表单
"use client"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { Button } from "@/components/ui/button"; import { Switch } from "@/components/ui/switch"; import { Textarea } from "@/components/ui/textarea"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; // 复用上面定义的表单Schema const formSchema = z.object({ chart: z.instanceof(File, { message: "请上传Chart文件" }), addContext: z.boolean(), context: z.string().when("addContext", { is: true, then: (schema) => schema.min(1, "请填写上下文内容"), otherwise: (schema) => schema.optional(), }), }); type FormValues = z.infer<typeof formSchema>; export default function ChartForm() { const { register, handleSubmit, formState: { errors }, watch, } = useForm<FormValues>({ resolver: zodResolver(formSchema), defaultValues: { addContext: false, context: "", }, }); // 监听开关状态,可选用于动态显示/隐藏文本域 const addContext = watch("addContext"); const onSubmit = (data: FormValues) => { // 处理表单提交逻辑 console.log("提交数据:", data); }; return ( <form onSubmit={handleSubmit(onSubmit)} className="space-y-4"> {/* Chart文件上传 */} <div className="space-y-2"> <Label htmlFor="chart">Chart文件</Label> <Input id="chart" type="file" {...register("chart")} className="file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100" /> {errors.chart && <p className="text-red-500 text-sm">{errors.chart.message}</p>} </div> {/* Add Context开关 */} <div className="flex items-center space-x-2"> <Switch id="addContext" {...register("addContext")} /> <Label htmlFor="addContext">添加上下文</Label> </div> {/* Context文本域(开关开启时才显示) */} {addContext && ( <div className="space-y-2"> <Label htmlFor="context">上下文内容</Label> <Textarea id="context" {...register("context")} placeholder="请输入上下文信息" /> {errors.context && <p className="text-red-500 text-sm">{errors.context.message}</p>} </div> )} <Button type="submit">提交表单</Button> </form> ); }
关键说明
- Zod的
when方法会根据addContext字段的值动态切换验证规则:开关开启时context必填,关闭时该字段设为可选,不会触发验证报错。 - 用
watch监听开关状态,动态显示/隐藏文本域,既符合逻辑也能提升用户体验(即使不隐藏,验证规则也会自动跳过)。 - 必须通过
zodResolver将Zod Schema关联到React Hook Form,才能让条件验证生效。
内容的提问来源于stack exchange,提问作者HKS
相关产品推荐
相关产品推荐

