You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:56:18