Skip to content
返回构建教程

表单流水线

用 schema 验证、可访问输入和渐进增强构建表单。

为什么

表单是用户给你数据的主要方式——注册、结账、设置——坏表单体验直接损转化。zod + react-hook-form 表单流水线给你:schema 驱动验证(客户端服务端单一事实源)、默认可访问(label、aria、错误关联)、渐进增强(无 JS 可用、blur 验证、enter 提交)。没有它,表单是 useState 堆 + 手动验证 + 临时错误消息,不一致、不可访问、不匹配服务端验证。schema 驱动意味着加字段是一行 schema 变更非 5 文件编辑。

何时使用

应用有 ≥1 用户输入表单时。搭流水线约 1-2 小时。只读应用可跳过。

如何做

1. 用 zod 定义表单 schema——单一事实源
   - const schema = z.object({ email: z.string().email(), password: z.string().min(8) })
   - 跨字段验证加 refine()(密码确认匹配)

2. 用 react-hook-form 加 zodResolver 把 schema 接表单
   - const form = useForm({ resolver: zodResolver(schema) })
   - register("email") 给你 onChange、onBlur、ref 和错误状态

3. 建可访问输入组件:label + input + 错误消息
   - <label htmlFor="email"> + <input id="email" aria-invalid={!!error} aria-describedby="email-error" />
   - 错误:<p id="email-error" role="alert">{error.message}</p>

4. 用同 schema 重验证的 server action 提交
   - 永不仅信客户端验证——服务端是权威
   - 返回表单可显示的类型化错误(字段→消息)

5. 加渐进增强:无 JS 表单可用
   - 用原生 <form action={serverAction}> 无 JS 提交
   - JS 增强内联验证,但回退是正常 POST

示例

import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";

const schema = z.object({
  email: z.string().email("输入有效邮箱"),
  password: z.string().min(8, "至少 8 字符"),
});
type FormData = z.infer<typeof schema>;

export function SignupForm() {
  const { register, handleSubmit, formState: { errors } } = useForm<FormData>({ resolver: zodResolver(schema) });
  return (
    <form action={signupAction} onSubmit={handleSubmit(onSubmit)}>
      <label htmlFor="email">邮箱</label>
      <input id="email" type="email" {...register("email")} aria-invalid={!!errors.email} aria-describedby="email-err" />
      {errors.email && <p id="email-err" role="alert">{errors.email.message}</p>}
      <button type="submit">注册</button>
    </form>
  );
}

常见问题

  • ⚠仅提交时验证,用户填全表单才知第一字段错。
  • ⚠label 未关联 input(无 htmlFor/id),屏幕阅读器报'编辑文本'无上下文。
  • ⚠客户端服务端验证消息不同,用户修客户端错得不同服务端错。
  • ⚠验证时禁提交按钮,JS 禁用用户永不提交。

最佳实践

  • ✓blur 时验证(非每键)给即时反馈不烦人。
  • ✓客户端服务端用同 zod schema,验证按构造一致。
  • ✓清晰显示成功状态(绿勾、确认消息)——用户需知表单成了。
  • ✓长表单分步带进度指示和每步验证。