表单

React Hook Form + Zod / TanStack Form

推荐

React Hook Form + Zod

用的人多,遇到问题一搜就能找到答案。shadcn/ui 的表单也是这个组合

比较效果

用每个库做了同样的东西,动手试试看。

React Hook Form + Zod
TanStack Form

比较代码

修改代码,右边的预览会跟着变化。

在你自己的项目里运行这个示例:npx shadcn@latest add button input label

import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { z } from "zod"
import { Button } from "./components/ui/button"
import { Input } from "./components/ui/input"
import { Label } from "./components/ui/label"

// ① 规则:把所有校验规则集中写在一处
const schema = z.object({
  email: z.email("请输入有效的邮箱地址"),
  password: z.string().min(8, "至少需要 8 个字符").regex(/[0-9]/, "请至少包含一个数字"),
})

// 根据规则生成表单值的类型
type FormValues = z.infer<typeof schema>

export default function App() {
  // 创建表单(规则通过 zodResolver 传入)
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<FormValues>({ resolver: zodResolver(schema) })

  // 只有全部规则都通过时才会调用
  const onSubmit = (values: FormValues) => {
    alert("已登录:" + values.email)
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-4 p-5">
      <div className="flex flex-col gap-2">
        <Label htmlFor="email">邮箱</Label>
        {/* ② 连接:把输入框接入表单 */}
        <Input id="email" {...register("email")} />
        {/* ③ 提示:不符合规则时显示错误 */}
        {errors.email && (
          <p className="text-sm text-destructive">{errors.email.message}</p>
        )}
      </div>

      <div className="flex flex-col gap-2">
        <Label htmlFor="password">密码</Label>
        <Input id="password" type="password" {...register("password")} />
        {errors.password && (
          <p className="text-sm text-destructive">{errors.password.message}</p>
        )}
      </div>

      <Button type="submit">登录</Button>
    </form>
  )
}

比较

截至 2026 年 10 月

React Hook Form + Zod

推荐官方网站 ↗

特点

最常用的组合。只要给输入框加上 register 就能收集值,校验规则则用 Zod 集中编写

适用场景

推荐。shadcn/ui 的表单也是用这个组合做的

TanStack Form

官方网站 ↗

特点

和 TanStack Query 等同属一个系列的较新的库。每个输入框都用 form.Field 包起来编写。类型(TypeScript)检查很细致

适用场景

想和 TanStack 的其他库保持一致。输入框很多,想靠类型避免出错