如何用shadcn、zod、react-hook-form为必填表单字段添加红色*
解决shadcn + zod + react-hook-form 必填字段红色*不显示的问题
你的代码无效是因为react-hook-form返回的field对象中并没有isOptional这个属性,所以!field.isOptional的判断逻辑根本不生效。要实现必填字段显示红色*,需要从定义校验规则的zod schema中获取字段的必填状态。
解决方案步骤:
- 确保你已经定义了完整的zod表单schema,明确标记哪些字段必填、哪些可选
- 在自定义表单字段组件中,从schema的
shape属性里获取对应字段的校验规则,通过isOptional属性判断是否为必填字段 - 用这个判断结果来控制红色*的显示
修改后的完整代码示例:
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
相关产品推荐
相关产品推荐

