Form với react-hook-form + zod
Ghép Field, Input, Select, Checkbox, DatePicker và Button của Yugen với react-hook-form + zod để có form kiểm tra dữ liệu đầy đủ, tiếng Việt, truy cập được.
react-hook-form, zod và @hookform/resolvers là peer tuỳ chọn — Yugen không phụ thuộc vào chúng; bạn tự cài: npm i react-hook-form zod @hookform/resolvers. Input / Select nhận thẳng register(name) (ref trỏ tới phần tử gốc). Control không phải phần tử form gốc (DatePicker, Checkbox) dùng Controller. Map lỗi vào Field bằng validationState="error" + validationMessage: Field tự gắn aria-invalid, aria-describedby và role="alert". Đặt noValidate trên <form> để bong bóng lỗi của trình duyệt không chen vào; nút gửi dùng loading={isSubmitting}.
Import
Cài từ npm, chép mã nguồn vào dự án bằng @yugen-ui/cli hoặc shadcn CLI, hoặc import thẳng khi làm việc trong repo này.
TSX
// npm install yugen-ui// Tuỳ chọn — tự cài: npm i react-hook-form zod @hookform/resolversimport { Controller, useForm } from "react-hook-form";import { zodResolver } from "@hookform/resolvers/zod";import { z } from "zod";import { Button, Checkbox, DatePicker, Field, Input, Select } from "yugen-ui";Biến thể
Mỗi ô là một mẫu độc lập: hover để Copy, hoặc bấm Code để xem mã nguồn.
Lỗi từ server với setError
Lỗi không đoán trước được ở client (email đã tồn tại) đặt bằng setError(..., { shouldFocus: true }) và hiện ngay trong Field.
Bước 1/3 · Đăng nhập
Bước 1/3: Đăng nhập
Kiểm tra theo bước với Wizard
validate của mỗi bước gọi trigger([...các trường của bước]) — trả Promise<boolean>, false thì Wizard chặn và báo lỗi.
Cách dùng
Nên
- Viết thông báo lỗi trong schema zod bằng tiếng Việt, nói rõ cách sửa ("Mật khẩu cần ít nhất 8 ký tự.").
- Dùng Controller cho DatePicker, Checkbox, Combobox… và truyền field.ref để focus được ô lỗi.
- Kiểm tra lại ở server; hiển thị lỗi server bằng setError trên đúng trường.
Không nên
- Không import react-hook-form / zod vào component thư viện — chúng chỉ là lựa chọn ở tầng ứng dụng.
- Không báo lỗi khi người dùng chưa rời ô lần đầu (mode "onChange" từ đầu gây khó chịu).
- Không vô hiệu hoá nút gửi khi form chưa hợp lệ — để người dùng bấm và thấy lỗi cụ thể.
Props
| Prop · Kiểu | Mặc định | Mô tả |
|---|---|---|
| register | Mặc định: — | Trải vào Input / Select / Textarea của Yugen: {...register("email")}. |
| Controllerreact-hook-form | Mặc định: — | Cho DatePicker (value + onValueChange), Checkbox / Switch (checked + onCheckedChange), Combobox… |
| Field | Mặc định: — | "error" khi errors.<tên> có giá trị → aria-invalid trên control. |
| Field | Mặc định: — | errors.<tên>?.message — hiện với role="alert" và được liên kết qua aria-describedby. |
| zodResolver | Mặc định: — | Dùng schema zod làm nguồn kiểm tra; z.infer<typeof schema> cho kiểu giá trị form. |
| trigger | Mặc định: — | Kiểm tra một phần form — dùng làm WizardStep.validate. |
| Button | Mặc định: — | loading={isSubmitting}: Spinner thay icon, giữ nguyên độ rộng, aria-busy. |