最近在浏览 shadcn/ui 的 表单文档 (Forms)。时发现它并没有去造一个全新的表单轮子而是推荐使用两个神仙库React Hook Form 和 Zod。为什么 shadcn/ui 会选择这个组合我使用下来总结有以下几点react-hook-form有极致的性能与状态管理Zod对表单校验规则的全面封装在表单场景中他俩就是天作之合、强强联手1. React Hook Form高性能的表单状态管理React Hook FormRHF是一个轻量、高性能的 React 表单库。它的核心理念是让表单尽可能接近原生 HTML form。相比传统的表单写法const[email,setEmail]useState()const[password,setPassword]useState()受控组件Controlled Components每次输入都会触发整个组件的重渲染。React Hook Form (RHF) 采用了非受控组件的思想用 ref 直接读取表单项的值。React Hook Form 的核心 APIReact Hook Form 的 API 非常少最核心的是以下几个。1 useFormuseForm用于创建表单实例。const{register,handleSubmit,control,reset,watch,formState}useForm()其中register注册字段handleSubmit处理提交control控制复杂组件formState表单状态2 register用于注册input字段它会返回 onChange、onBlur、name 和 ref。你可以直接用解构语法 {…register(‘字段名’)} 绑定到原生 上input {...register(email)} /这行代码实际上会注册字段到表单绑定 value、onChange、ref提交时 React Hook Form 会自动收集数据{email:exampleemail.com}3 handleSubmit处理表单提交。form onSubmit{handleSubmit(onSubmit)}constonSubmit(data){console.log(data)}4 formStateformState用于获取表单状态有errors,isSubmitting,isValid,dirtyFields,touchedFields等状态例如显示表单校验错误信息p{form.formState.errors.email?.message}/p二、Zod类型安全的 schema validation表单校验需要一套规则而 Zod 就是用来定义这些规则的。你只需要定义一次 Zod Schema它就能同时为你提供运行时校验和编译时的类型提示告别重复写 TS 接口和校验逻辑。例如import{z}fromzodconstUserSchemaz.object({name:z.string(),age:z.number(),})UserSchema.parse(data)如果数据不符合 schema就会抛出错误。Zod 常用 API字符串校验z.string()z.string().min(3)z.string().max(20)z.string().email()z.string().url()例如z.string().min(3,Too short)numberz.number().min(0)optionalz.string().optional()enumz.enum([todo,doing,done])objectz.object({title:z.string(),description:z.string()})类型推导z.infertypeof schema是 Zod 最魔法的 API 它可以直接根据你写的 Schema 反向推导出 TypeScript 的 type 或 interface.比如在我的项目中constformSchemaz.object({title:z.string().trim().min(1,Title is required.),description:z.string().trim().optional(),start:z.date().optional(),end:z.date().optional(),}).refine((v){if(!v.start||!v.end)returntrue;returnv.end.getTime()v.start.getTime();},{path:[end],message:End must be after start.,});typeFormDataz.infertypeofformSchema三、一个完整表单示例下面是一个包含“用户名”和“邮箱”的基础表单组件示例:importReactfromreact;import{useForm}fromreact-hook-form;import{z}fromzod;import{zodResolver}fromhookform/resolvers/zod;// 1. 使用 Zod 定义表单的数据模式 (Schema)constformSchemaz.object({username:z.string().min(2,{message:用户名至少需要 2 个字符}),email:z.string().email({message:请输入有效的邮箱地址}),});// 2. 利用 Zod 自动推导 TypeScript 类型typeFormDataz.infertypeofformSchema;exportdefaultfunctionMinimalForm(){// 3. 初始化 React Hook Formconst{register,handleSubmit,formState:{errors},}useFormFormData({resolver:zodResolver(formSchema),// 绑定 Zod 校验规则});// 4. 提交处理函数constonSubmit(data:FormData){console.log(验证通过的数据:,data);};return(form onSubmit{handleSubmit(onSubmit)}style{{display:flex,flexDirection:column,gap:1rem,width:300px}}{/* 用户名输入框 */}divlabel用户名/labelinput{...register(username)}placeholder输入用户名/{errors.usernamep style{{color:red}}{errors.username.message}/p}/div{/* 邮箱输入框 */}divlabel邮箱/labelinput{...register(email)}placeholder输入邮箱/{errors.emailp style{{color:red}}{errors.email.message}/p}/divbutton typesubmit提交/button/form);}总结shadcn/ui推荐这套方案不是没有原因的。React Hook Form 解决了“怎么高效收集和管理状态”的问题而 Zod 解决了“怎么优雅定义规则和类型”的问题。