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

如何用shadcn、zod、react-hook-form为必填表单字段添加红色*

解决shadcn + zod + react-hook-form 必填字段红色*不显示的问题

你的代码无效是因为react-hook-form返回的field对象中并没有isOptional这个属性,所以!field.isOptional的判断逻辑根本不生效。要实现必填字段显示红色*,需要从定义校验规则的zod schema中获取字段的必填状态。

解决方案步骤:

  1. 确保你已经定义了完整的zod表单schema,明确标记哪些字段必填、哪些可选
  2. 在自定义表单字段组件中,从schema的shape属性里获取对应字段的校验规则,通过isOptional属性判断是否为必填字段
  3. 用这个判断结果来控制红色*的显示

修改后的完整代码示例:

import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { FormItem, FormLabel, FormControl, FormMessage, Input } from "@/components/ui/form";

// 定义zod表单校验规则
const formSchema = z.object({
  username: z.string().min(2, "用户名至少2个字符"), // 必填字段
  email: z.string().email("请输入合法邮箱").optional(), // 可选字段
  phone: z.string().min(11, "手机号长度错误"), // 必填字段
});

type FormValues = z.infer<typeof formSchema>;

export default function MyForm() {
  const { register, formState: { errors } } = useForm<FormValues>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      username: "",
      email: "",
      phone: "",
    },
  });

  // 自定义可复用的表单字段组件
  const FormField = ({ fieldName, label }: { fieldName: keyof FormValues; label: string }) => {
    // 从zod schema中获取当前字段的校验规则
    const fieldSchema = formSchema.shape[fieldName];
    // 判断是否为必填字段:非可选即为必填
    const isRequired = !fieldSchema.isOptional;

    const field = register(fieldName);

    return (
      <FormItem>
        <FormLabel className="text-sm font-medium text-gray-700">
          {label}
          {/* 只有必填字段才显示红色* */}
          {isRequired && <span className="text-red-500 ml-1">*</span>}
        </FormLabel>
        <FormControl>
          <Input
            {...field}
            className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
          />
        </FormControl>
        <FormMessage>{errors[fieldName]?.message}</FormMessage>
      </FormItem>
    );
  };

  return (
    <form className="space-y-4">
      <FormField fieldName="username" label="用户名" />
      <FormField fieldName="email" label="邮箱" />
      <FormField fieldName="phone" label="手机号" />
      <button type="submit" className="px-4 py-2 bg-indigo-600 text-white rounded-md">提交</button>
    </form>
  );
}

关键说明:

  • zod的字段校验规则对象自带isOptional属性,直接通过formSchema.shape[fieldName].isOptional就能获取字段是否为可选状态
  • 替换掉原来错误的field.isOptional判断逻辑,改用从zod schema获取的状态,就能正确控制红色*的显示

内容的提问来源于stack exchange,提问作者RakibulB

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 01:53:16