Mundarija (28)
- Bu darsda
- 1. Nega bu kerak?
- 2. Bitta forma — besh xil
- 2.1 Tajriba
- 2.2 React'ning o'zi: <form action>
- 2.3 React Hook Form
- 2.4 Formik
- 2.5 TanStack Form
- 2.6 Conform
- 3. Narxi: o'lchov
- 3.1 Forma kutubxonalari
- 3.2 Sxema kutubxonalari
- 4. Standard Schema — umumiy rozetka
- 4.1 Interfeys
- 4.2 O'z resolveringiz — istalgan sxema uchun
- 5. Sxema kutubxonalari
- 5.1 Valibot
- 5.2 ArkType va Yup
- 5.3 Qaysi biri?
- 6. vazifalar da: biz sinab ko'rdik
- 7. Ko'p uchraydigan xatolar
- 8. Mashqlar
- 1-mashq (oson): kutubxonani tanlang
- 2-mashq (o'rta): Standard Schema bilan tekshiruvchi
- 3-mashq (qiyin): xatolar ro'yxati — criteriaMode: "all"
- 9. Real ishda
- Xulosa
- Manbalar
Forma va validatsiya kutubxonalari: Formik, TanStack Form, Conform, Valibot va Standard Schema
Qisqacha: Forma kutubxonasi (qiymat, xato, yuborish holati) va sxema kutubxonasi (qoidalar) — ikki alohida tanlov. Ularni Standard Schema — sxemalarning umumiy interfeysi (
schema["~standard"].validate) — bog'laydi: Zod, Valibot, ArkType bir xil "rozetka"ga ulanadi. Bizning o'lchovda bitta formaning narxi (React bilan, gzip): kutubxonasiz<form action>72.2 KB, RHF 84.6, Formik 84.2, TanStack Form 88.3, Conform 93.7. Sxema: Zod 23.7 KB,zod/mini5.8, Valibot 1.6. Eng yaxshisi yo'q — vaziyatga mosi bor.
Bu darsda
- Bitta formani besh xil (React'ning o'zi, RHF, Formik, TanStack Form, Conform) o'qiysiz va farqini tushuntira olasiz.
- Har kutubxonaning hajmini haqiqiy o'lchov bilan solishtirasiz.
- Standard Schema nima ekanini ko'rasiz va unga ulanadigan o'z resolveringizni yozasiz.
- Valibot, ArkType va Yup ni Zod bilan solishtirasiz va qaysi vaziyatda qaysi biri to'g'ri tanlov ekanini aytasiz.
Oldin bilishingiz kerak: RHF III, RHF + Zod: resolver, Zod va turni sxemadan chiqarish, useActionState va useFormStatus.
1. Nega bu kerak?
To'rt darsda React Hook Form va Zod bilan ishladik. Sardor ishga kirgan kompaniyada esa boshqa narsa: eski admin panel Formik va Yup da, yangi Next.js loyiha Conform da, yaqinda qo'shilgan jamoa TanStack Form ni taklif qilyapti. U birinchi kunidan bu kodni o'qishi va "nega aynan shu?" degan savolga javob berishi kerak.
Bu dars "eng yaxshi kutubxona" ni topmaydi. U har birining qaysi muammoni hal qilishini va narxini ko'rsatadi. Hayotiy o'xshatish: transport. Toshkent ichida metro tez, qishloqqa esa mashina kerak, og'ir yuk uchun — yuk mashinasi. "Eng yaxshi transport" yo'q, "bu yo'lga mosi" bor.
Avval ikki tanlovni ajratib olaylik:
| Tanlov | Nima qiladi | Variantlar |
|---|---|---|
| forma kutubxonasi | qiymatlar, xatolar, isSubmitting, isDirty, dinamik maydonlar |
React'ning o'zi, RHF, Formik, TanStack Form, Conform |
| sxema kutubxonasi | qoidalar, tur chiqarish, transform | Zod, zod/mini, Valibot, ArkType, Yup |
Ular mustaqil: RHF Valibot bilan ham, TanStack Form Zod bilan ham ishlaydi. Bog'lovchi — resolver yoki Standard Schema («Standard Schema — umumiy rozetka» bo'limida).
2. Bitta forma — besh xil
2.1 Tajriba
vazifalar uchun forma tanlashdan oldin biz bitta kichik vazifani besh usulda yozdik: matn (majburiy, chetlari kesiladi, ≤ 100 belgi) va "bajarildi" katagi. Sxema hammasida bir xil — zod/mini (Zod chuqurroq). Har variant alohida Vite build qilindi va hajmi o'lchandi (gzip -9), turlari tsc bilan tekshirildi. Fayllar — kanondagi sinov/19/tajriba/variantlar/ (kanonga kirmagan tajriba).
Bu kutubxonalar saytdagi natija oynasida yo'q — quyidagi bloklar «Ishga tushir» siz, kanon tajribasidan aynan. O'z loyihangizda npm install bilan sinab ko'rishingiz mumkin (versiyalar pastdagi jadvalda).
Umumiy sxema (kanon, _forma.ts):
import { z } from "zod/mini";
export const formaSxemasi = z.object({
matn: z.string().check(
z.trim(),
z.minLength(1, "Vazifa matnini yozing."),
z.maxLength(100, "Matn juda uzun."),
),
bajarildi: z.boolean(),
});
export type FormaQiymati = z.output<typeof formaSxemasi>;Tajriba fayllarida ko'p narsa bir qatorga yozilgan (ular o'lchov uchun). Bu yerda ular telefonga sig'ishi uchun qatorlarga bo'lingan — kodning o'zi o'zgarmagan.
2.2 React'ning o'zi: <form action>
Kutubxonasiz — useActionState bilan (kanon, forma-native.tsx):
function Forma() {
const [holat, action] = useActionState(
(_: { xato: string | null; matn: string }, f: FormData) => {
const n = formaSxemasi.safeParse({
matn: String(f.get("matn") ?? ""),
bajarildi: f.get("bajarildi") === "on",
});
if (!n.success)
return {
xato: n.error.issues[0]?.message ?? null,
matn: String(f.get("matn") ?? ""),
};
yubor(n.data);
return { xato: null, matn: "" };
},
{ xato: null, matn: "" },
);
return (
<form noValidate action={action}>
<input
aria-label="Matn"
name="matn"
defaultValue={holat.matn}
/>
<p>{holat.xato}</p>
<input
type="checkbox"
aria-label="Bajarildi"
name="bajarildi"
/>
<button>Saqlash</button>
</form>
);
}FormData dan qiymatlar qo'lda olinadi, checkbox — "on" yoki yo'q (Zod chuqurroq dagi jadval). Xato — bitta umumiy. defaultValue={holat.matn} — action'dan keyin matn yo'qolmasin (Formalar II). Bu — vazifalar dagi tezkor formaning yo'li.
2.3 React Hook Form
Kanon, forma-rhf.tsx:
function Forma() {
const { register, handleSubmit, formState } = useForm({
resolver: zodResolver(formaSxemasi),
defaultValues: { matn: "", bajarildi: false },
});
return (
<form noValidate onSubmit={(e) => void handleSubmit(yubor)(e)}>
<input aria-label="Matn" {...register("matn")} />
<p>{formState.errors.matn?.message}</p>
<input
type="checkbox"
aria-label="Bajarildi"
{...register("bajarildi")}
/>
<button>Saqlash</button>
</form>
);
}Tanish: uncontrolled maydonlar, register, resolver (RHF I – RHF III).
2.4 Formik
Formik (2.4.9) — RHF dan oldingi davrning eng mashhur forma kutubxonasi. Bugun u "eski" (legacy) hisoblanadi: yangi loyihada kam tanlanadi, lekin eski kodda juda ko'p uchraydi. Kanon, forma-formik.tsx:
function Forma() {
return (
<Formik
initialValues={{ matn: "", bajarildi: false }}
validate={(q) => {
const n = formaSxemasi.safeParse(q);
return n.success
? {}
: Object.fromEntries(
n.error.issues.map((i) => [String(i.path[0]), i.message]),
);
}}
onSubmit={(q) => yubor(formaSxemasi.parse(q))}
>
{({ errors }) => (
<Form noValidate>
<Field name="matn" aria-label="Matn" />
<p>{errors.matn}</p>
<Field
type="checkbox"
name="bajarildi"
aria-label="Bajarildi"
/>
<button type="submit">Saqlash</button>
</Form>
)}
</Formik>
);
}Farqlar:
- Controlled. Formik qiymatlarni o'z state'ida saqlaydi — har harfda forma qayta chiziladi. RHF ning "uncontrolled" yo'li aynan shu muammoga javob sifatida paydo bo'lgan.
- Render prop —
{({ errors }) => …}(render props). Hook'lar davridan oldingi naqsh; Formik'dauseFormikhook'i ham bor. validate— Zod resolveri o'rniga, xatolarni o'zimiz{ maydon: xabar }ga aylantirdik (shu blokdagiObject.fromEntries). Formik'ning "o'z" sxema kutubxonasi — Yup (validationSchema).
Qachon to'g'ri tanlov: mavjud Formik loyihasi. Ishlab turgan formani ko'chirish — RHF I dagi "ko'chirmaslik" qarori bilan bir xil savol: foyda xavfdan kattami?
2.5 TanStack Form
TanStack Form (1.33.5) — TanStack Query va Router mualliflarining forma kutubxonasi. Asosiy g'oyasi — turlar: maydon nomi, qiymati va xatosi butunlay type-safe. Kanon, forma-tanstack.tsx:
function Forma() {
const forma = useForm({
defaultValues: { matn: "", bajarildi: false },
validators: { onSubmit: formaSxemasi },
onSubmit: ({ value }) => yubor(formaSxemasi.parse(value)),
});
return (
<form
noValidate
onSubmit={(e) => {
e.preventDefault();
void forma.handleSubmit();
}}
>
<forma.Field name="matn">
{(f) => (
<>
<input
aria-label="Matn"
value={f.state.value}
onChange={(e) => f.handleChange(e.target.value)}
onBlur={f.handleBlur}
/>
<p>
{f.state.meta.errors.map((x) => x?.message).join(", ")}
</p>
</>
)}
</forma.Field>
<forma.Field name="bajarildi">
{(f) => (
<input
type="checkbox"
aria-label="Bajarildi"
checked={f.state.value}
onChange={(e) => f.handleChange(e.target.checked)}
/>
)}
</forma.Field>
<button>Saqlash</button>
</form>
);
}E'tibor bering: validators: { onSubmit: formaSxemasi } — sxema to'g'ridan berildi, resolver yo'q. TanStack Form Standard Schema'ni o'zi tushunadi (pastda, «Standard Schema» bo'limida). Har maydon — forma.Field komponenti, ichida controlled <input> (qiymat va handleChange qo'lda ulanadi). Kod uzunroq, lekin name="matnn" deb xato yozsangiz — tsc darhol ushlaydi.
Qachon to'g'ri tanlov: TypeScript'ga qattiq tayanadigan jamoa, murakkab formalar, TanStack ekotizimi (Query, Router, Table) allaqachon ishlatilgan loyiha.
2.6 Conform
Conform (1.21.1) — server action'lar uchun yaratilgan. Asosiy g'oyasi — progressiv yaxshilash (progressive enhancement): forma JavaScript yuklanmasa ham ishlaydi (oddiy HTML forma bo'lib yuboriladi), JavaScript bilan esa jonli xatolar qo'shiladi. Kanon, forma-conform.tsx:
function Forma() {
const [forma, maydonlar] = useForm({
onValidate: ({ formData }) =>
parseWithZod(formData, { schema: formaSxemasi }),
onSubmit: (e, { submission }) => {
e.preventDefault();
if (submission?.status === "success") yubor(submission.value);
},
});
return (
<form id={forma.id} noValidate onSubmit={forma.onSubmit}>
<input aria-label="Matn" name={maydonlar.matn.name} />
<p>{maydonlar.matn.errors}</p>
<input
type="checkbox"
aria-label="Bajarildi"
name={maydonlar.bajarildi.name}
/>
<button>Saqlash</button>
</form>
);
}parseWithZod(formData, …) — FormData ni sxemaga moslab o'giradi (checkbox "on" → true, bo'sh satr → undefined) va tekshiradi. Xuddi shu funksiya serverda ham ishlaydi: Next.js server action (Server Actions I) formani oladi, parseWithZod qiladi, xato bo'lsa — qaytaradi, Conform uni maydonlar ostiga qo'yadi.
Qachon to'g'ri tanlov: Next.js / Remix server action'lari, JavaScript'siz ham ishlashi muhim bo'lgan formalar (sekin internet, eski telefon).
Tekshirib ko'ring: "Sekin internetda sahifa ochildi, JavaScript hali yuklanmadi, mehmon «Yuborish» ni bosdi." Qaysi variantlar ishlaydi?
Javob
React'ning <form action> (server action bilan, Next.js'da) va Conform — ular oddiy HTML forma sifatida yuboriladi va server javob beradi. RHF, Formik, TanStack Form esa onSubmit hodisasiga tayanadi: JavaScript yo'q — hodisa ham yo'q, brauzer formani action siz joriy sahifaga yuboradi (yoki hech narsa bo'lmaydi). Bizning SPA (vazifalar) da bu farq yo'q: JavaScript'siz ilovaning o'zi yo'q.
3. Narxi: o'lchov
3.1 Forma kutubxonalari
Hamma variant — bir xil React 19.3.0 va zod/mini sxemasi bilan. Raqam — brauzer yuklaydigan butun JavaScript (gzip -9). Kanon natijalar/tajriba/hajm.txt dan (Node 24.21.0, Vite 8.3.3):
variant xom B gzip B qator
forma-conform 306960 93744 22
forma-formik 272271 84163 25
forma-native 233664 72242 20
forma-rhf 268141 84597 19
forma-tanstack 299038 88270 33- <form action> (kutubxonasiz)72,2 KB
- Formik 2.4.984,2 KB
- React Hook Form 7.89.084,6 KB
- TanStack Form 1.33.588,3 KB
- Conform 1.21.193,7 KB
Manba: O'lchandi: sinov/19/tajriba (Vite 8.3.3, gzip -9), natijalar/tajriba/hajm.txt, 2026-10-13
Kutubxonasiz variantga nisbatan qo'shimcha:
| Kutubxona | + KB (gzip) | Manba qatori |
|---|---|---|
| Formik | +11.9 | 25 |
| React Hook Form (+ resolvers) | +12.4 | 19 |
| TanStack Form | +16.0 | 33 |
Conform (+ @conform-to/zod) |
+21.5 | 22 |
Uch xulosa:
- Farqlar kichik — 12–22 KB. Bu bitta o'rtacha rasmdan kam. Kutubxona tanlovini hajm emas, qulaylik va jamoa hal qiladi.
- Kutubxonasiz eng kichik — lekin unda
isDirty, maydon xatolari, dinamik ro'yxat yo'q. Ularni qo'lda yozsangiz, kod ham, hajm ham o'sadi. - Qator soni — taxminiy "qulaylik" o'lchovi: RHF eng qisqa (19), TanStack Form eng uzun (33) — type-safe'lik uchun maydonlar aniq ulanadi.
Bu o'lchov hajm va turlar haqida: variantlar build qilindi va tsc dan xatosiz o'tdi (natijalar/tajriba/tip.txt — exit 0), lekin brauzerda bosib sinalmagan. Tezlikni (render soni) o'lchamadik.
3.2 Sxema kutubxonalari
Faqat sxema — vazifalar dagi API sxemasi (vazifa va ro'yxat), uch kutubxonada. Bu yerda React yo'q, faqat sxema kodi:
variant xom B gzip B qator
sxema-valibot 4972 1648 8
sxema-zod 83576 23653 8
sxema-zodmini 17390 5778 8- Zod 4.6.5 (klassik)23,7 KB
- zod/mini 4.6.55,8 KB
- Valibot 1.5.01,6 KB
Manba: O'lchandi: sinov/19/tajriba (Vite 8.3.3, gzip -9), natijalar/tajriba/hajm.txt, 2026-10-13
Valibot zod/mini dan ham 4.2 KB kichik. Sababi — tuzilish: har tekshiruv alohida funksiya, bundler ishlatilmaganini tashlaydi ("tree shaking", Tree shaking). zod/mini aynan shu g'oyani Zod'ga olib kirgan (Zod va turni sxemadan chiqarish darsida ko'rgansiz). Klassik Zod bu yerda 23.7 KB — faqat sxema kodi. vazifalar build'ida u +24.2 KB edi (API qatlami darsidagi o'lchov): o'lchov usuli boshqa, xulosa bir xil.
Nega vazifalar da baribir Zod? Uch sabab. Birinchisi — kurs yo'nalishi: Zod — eng keng tarqalgan sxema kutubxonasi, serverda (25-qism) ham shu. Ikkinchisi — 4.2 KB vazifalar ning 153.7 KB idan 3% ga yaqin. Uchinchisi — RHF va Zod jufti eng ko'p hujjat va misolga ega. Bu — halol qaror, "Valibot yomon" degani emas: hajm muhim bo'lgan joyda (vidjet, boshqa saytga qo'yiladigan skript) Valibot to'g'ri tanlov.
4. Standard Schema — umumiy rozetka
4.1 Interfeys
Zod va turni sxemadan chiqarish darsida Standard Schema bilan tanishgansiz: har sxemada ~standard xususiyati bor, ichida validate(value). Natija — { value } yoki { issues }. TanStack Form sxemani resolver'siz qabul qilgani shundan: u Zod'ni bilmaydi, faqat standartni biladi.
zod/mini sxemasi ham standartni qo'llaydi — natija oynasida ko'ramiz:
import { z } from "zod/mini";
const Name = z
.string()
.check(z.trim(), z.minLength(2, "Kamida 2 harf"));
const std = Name["~standard"];
console.log(std.vendor, std.version);
console.log(std.validate(" Ali "));
console.log(std.validate("A").issues[0].message);Konsolda:
zod 1
{value: 'Ali'}
Kamida 2 harfvendor — kutubxona nomi, version — standartning versiyasi (1). Muvaffaqiyatda — { value } (kesilgan matn), xatoda — { issues } massivi, har elementida message va path.
4.2 O'z resolveringiz — istalgan sxema uchun
RHF + Zod darsida Zod uchun resolver yozgan edik. Endi u istalgan Standard Schema sxemasi bilan ishlaydi:
import { useForm } from "react-hook-form";
import { z } from "zod/mini";
function standardResolver(schema) {
return async (values) => {
const result = await schema["~standard"].validate(values);
if (!result.issues) return { values: result.value, errors: {} };
const errors = {};
for (const issue of result.issues) {
const name = (issue.path ?? []).join(".");
errors[name] ??= { type: "schema", message: issue.message };
}
return { values: {}, errors };
};
}
const Booking = z.object({
name: z
.string()
.check(z.trim(), z.minLength(2, "Ism kamida 2 harf")),
});
export default function App() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
resolver: standardResolver(Booking),
defaultValues: { name: "" },
});
return (
<form noValidate onSubmit={handleSubmit((d) => console.log(d))}>
<p>
<label htmlFor="name">Ism</label>
<input id="name" {...register("name")} />
</p>
<p role="alert">{errors.name?.message}</p>
<button>Yuborish</button>
</form>
);
}Ekranda:
Ism
Ism kamida 2 harf
YuborishstandardResolver ichida "zod" so'zi yo'q. Booking ni Valibot yoki ArkType sxemasiga almashtirsangiz, forma o'zgarmaydi. @hookform/resolvers da tayyori bor — @hookform/resolvers/standard-schema (standardSchemaResolver). validate Promise qaytarishi mumkin (async sxema), shuning uchun await.
flowchart LR
Z["Zod"] --> S["~standard.validate"]
V["Valibot"] --> S
A["ArkType"] --> S
S --> R["RHF (resolver)"]
S --> T["TanStack Form"]
S --> C["tRPC, server"]5. Sxema kutubxonalari
5.1 Valibot
Valibot'da metod zanjiri yo'q — har tekshiruv alohida funksiya, v.pipe bilan ulanadi. Bron sxemasi (Valibot natija oynasida yo'q, shuning uchun bu blok Node'da tekshirilgan):
import * as v from "valibot";
const Booking = v.object({
name: v.pipe(
v.string(),
v.trim(),
v.minLength(2, "Ism kamida 2 harf"),
),
guests: v.pipe(
v.string(),
v.transform(Number),
v.integer("Butun son yozing"),
v.minValue(1, "Kamida 1 kishi"),
v.maxValue(12, "Ko'pi bilan 12 kishi"),
),
});
type Booking = v.InferOutput<typeof Booking>;
const ok = v.safeParse(Booking, { name: " Malika ", guests: "4" });
console.log(ok.success && ok.output);
const bad = v.safeParse(Booking, { name: "A", guests: "15" });
console.log(bad.issues?.map((i) => i.message));Konsolda:
{ name: 'Malika', guests: 4 }
[ 'Ism kamida 2 harf', "Ko'pi bilan 12 kishi" ]Zod bilan solishtiring: z.string().trim().min(2, …) → v.pipe(v.string(), v.trim(), v.minLength(2, …)). coerce yo'q — o'rniga v.transform(Number) quvur ichida. Turni chiqarish — v.InferOutput (va v.InferInput). Natija — output (Zod'da data). Konsol bu yerda Node formatida ({ name: 'Malika', … }).
5.2 ArkType va Yup
Ularni o'lchamadik va kursda o'rnatmadik — faqat ko'rinishi, ular haqida bilish uchun.
ArkType — sxema TypeScript turiga o'xshash satr bilan yoziladi:
import { type } from "arktype";
const Booking = type({
name: "string >= 2",
guests: "1 <= number.integer <= 12",
});"string >= 2" — "kamida 2 belgili satr". TypeScript'ni yaxshi biladigan jamoaga qisqa va tanish; tezligi bilan ham tanilgan. Standard Schema'ni qo'llaydi.
Yup — Zod'dan oldingi davrning eng mashhur sxema kutubxonasi, Formik bilan juftlikda:
import * as yup from "yup";
const Booking = yup.object({
name: yup.string().trim().min(2, "Ism kamida 2 harf").required(),
guests: yup.number().integer().min(1).max(12).required(),
});Zanjir Zod'ga o'xshaydi. Farqi — TypeScript turlari keyinroq qo'shilgan, .required() ni har maydonga yozish kerak (sukut bo'yicha ixtiyoriy). Bugun u ham eski (legacy) hisoblanadi: eski Formik loyihalarida ko'p uchraydi.
5.3 Qaysi biri?
| Vaziyat | Forma | Sxema |
|---|---|---|
| oddiy SPA, ko'p formalar, katta jamoa | RHF | Zod / zod/mini |
| bitta-ikki kichik forma | React <form action> |
zod/mini yoki qo'lda |
| Next.js server action, JS'siz ham ishlashi kerak | Conform yoki <form action> |
Zod |
| qattiq type-safe, TanStack ekotizimi | TanStack Form | Zod / Valibot (Standard Schema) |
| hajm juda muhim (vidjet, embed) | React <form action> |
Valibot |
| eski loyiha | Formik | Yup |
Tekshirib ko'ring: Jamoa RHF + Zod dan RHF + Valibot ga o'tmoqchi. Formalarning qaysi qismi o'zgaradi?
Javob
Faqat sxemalar va resolver importi: zodResolver(schema) → valibotResolver(schema) (yoki standardSchemaResolver). register, errors, Controller, useFieldArray — hammasi o'sha. Ajratish shuning uchun foydali: forma va qoidalar mustaqil almashadi. Sxema bilan ishlaydigan boshqa joylar (server, testlar, API qatlami) esa qayta yoziladi — bu o'tishning asosiy narxi.
6. vazifalar da: biz sinab ko'rdik
Bu darsda vazifalar ga qadam yo'q — kanonga hech narsa kirmadi. Lekin qaror o'lchov bilan qilingan. Tajriba fayllari — sinov/19/tajriba/variantlar/forma-*.tsx va sxema-*.tsx, natija — natijalar/tajriba/hajm.txt (Node 24.21.0, Vite 8.3.3, gzip -9, 2026-10-13). Versiyalar tajriba/package.json da aniq yozilgan: Formik 2.4.9, TanStack Form 1.33.5, Conform 1.21.1 (@conform-to/zod bilan), Valibot 1.5.0, RHF 7.89.0, @hookform/resolvers 5.9.1.
Qaror va sabablari:
- Forma — RHF. Kutubxonasiz variantdan +12.4 KB (
vazifalarbuild'ida +14.7 KB — u yerda tahrir formasining o'z kodi ham qo'shilgan), lekinisDirty, maydon xatolari,Controller,useFieldArray— tahrir formasi va wizard'ga aynan shular kerak edi. Formik — o'xshash hajm, lekin controlled va eski uslub. TanStack Form — +3.6 KB ko'proq va kod uzunroq; bizning formalar oddiy. Conform — server action'lar uchun, bizda esa SPA va soxta API. - Sxema —
zod/mini. Valibot 4.2 KB kichik — o'lchovda shu ko'rinib turibdi. Lekin Zod — kurs yo'nalishi va server qismlarida ham ishlatiladi. Yakuniy hajmda 4 KB — taxminan 3%. - Ro'yxat sahifasidagi tezkor forma — React
<form action>(RHF I dagi qaror) — kichik forma uchun kutubxonasiz yo'l.
Raqamlarni o'zingiz ham takrorlay olasiz: har variantni alohida Vite loyihada build qiling (npm run build) va dist/assets dagi JS fayllarning gzip hajmini qo'shing. Biz buni har variantni ketma-ket build qiladigan kichik Node skripti bilan qildik.
7. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| "X kutubxonasi tezroq" — o'lchovsiz qaror | maqola yoki reklama raqami | o'z formangizni o'lchang (shu darsdagidek) |
| Formik'da har harfda butun forma sekin | controlled — har o'zgarish render | FastField yoki RHF; katta formani bo'laklang |
| Yup'da maydon ixtiyoriy bo'lib qoldi | .required() yozilmagan |
har majburiy maydonga .required() |
Valibot'da "4" son emas |
coerce yo'q |
v.pipe(v.string(), v.transform(Number), …) |
| Conform formasi serverdan kelgan xatoni ko'rsatmaydi | lastResult uzatilmagan |
server action natijasini useForm({ lastResult }) ga bering |
| kutubxona almashtirilganda hamma formalar buzildi | forma va sxema aralash yozilgan | sxemani alohida faylda, resolver orqali ulang |
8. Mashqlar
Mashqlar kurs/mashqlar/19/34-muqobillar/ da.
1-mashq (oson): kutubxonani tanlang
Har vaziyatga «Qaysi biri?» bo'limidagi jadvaldan mosini yozing — forma kutubxonasi nomi bilan (RHF, Formik, Conform, TanStack Form yoki action).
- Next.js'da obuna formasi, JavaScript'siz ham ishlashi kerak →
- 40 maydonli admin anketa, dinamik ro'yxatlar →
- 2019-yilda yozilgan loyihaga yangi maydon qo'shish, u yerda Formik →
- Bitta maydonli "qidirish" →
Yechim
- Conform (yoki React
<form action>server action bilan) — progressiv yaxshilash. - RHF — ko'p maydon,
useFieldArray, kam render. - Formik — mavjud loyihada o'sha kutubxona; bitta maydon uchun ko'chirish arzimaydi.
- action — React'ning
<form action>, kutubxona kerak emas.
2-mashq (o'rta): Standard Schema bilan tekshiruvchi
check(schema, value) funksiyasini yozing. U istalgan Standard Schema sxemasini oladi va qaytaradi: muvaffaqiyatda — "✓ " + qiymat, xatoda — "✗ " + xabarlar ("; " bilan). Uni ikki xil sxema bilan sinang: klassik zod va zod/mini (ikkalasi ham natija oynasida bor).
import { z } from "zod";
import { z as mini } from "zod/mini";
function check(schema, value) {
// shu yerga
return "?";
}
const Price = z.coerce.number().min(1000, "Kamida 1 000 so'm");
const Dish = mini.string().check(mini.minLength(2, "Nom qisqa"));
console.log(check(Price, "35000"));
console.log(check(Dish, "O"));Konsolda:
?
?Yechim
import { z } from "zod";
import { z as mini } from "zod/mini";
function check(schema, value) {
const result = schema["~standard"].validate(value);
if (result instanceof Promise) return "✗ async sxema";
if (result.issues) {
return "✗ " + result.issues.map((i) => i.message).join("; ");
}
return "✓ " + result.value;
}
const Price = z.coerce.number().min(1000, "Kamida 1 000 so'm");
const Dish = mini.string().check(mini.minLength(2, "Nom qisqa"));
console.log(check(Price, "35000"));
console.log(check(Dish, "O"));
console.log(check(Price, "500"));Konsolda:
✓ 35000
✗ Nom qisqa
✗ Kamida 1 000 so'mcheck hech qaysi kutubxonani import qilmaydi — faqat ~standard ga murojaat qiladi. Ikki xil "Zod" — bir xil natija. Valibot sxemasi ham shu funksiyaga to'g'ridan tushadi (Zod va turni sxemadan chiqarish darsidagi check misolining o'zi, endi brauzerda).
3-mashq (qiyin): xatolar ro'yxati — criteriaMode: "all"
«Standard Schema» bo'limidagi standardResolver har maydonga birinchi xatoni qo'yadi. Uni kengaytiring: maydonning barcha xabarlari types obyektida bo'lsin ({ type, message, types: { "0": "…", "1": "…" } }) — RHF criteriaMode: "all" da shu ko'rinishni kutadi. Parol maydoni (password): kamida 8 belgi va kamida bitta raqam. Ekranda hamma xabarlar ro'yxat bo'lib chiqsin.
Ishora: sxemada ikki qoida — mini.minLength(8, …) va mini.regex(/\d/, …). zod/mini birinchi xatodan keyin to'xtamaydi — ikkalasi ham issues da bo'ladi. Ekranda: Object.values(errors.password?.types ?? {}).
Yechim
import { useForm } from "react-hook-form";
import { z } from "zod/mini";
function standardResolver(schema) {
return async (values) => {
const result = await schema["~standard"].validate(values);
if (!result.issues) return { values: result.value, errors: {} };
const errors = {};
for (const issue of result.issues) {
const name = (issue.path ?? []).join(".");
errors[name] ??= {
type: "schema",
message: issue.message,
types: {},
};
const types = errors[name].types;
types[Object.keys(types).length] = issue.message;
}
return { values: {}, errors };
};
}
const Account = z.object({
password: z.string().check(
z.minLength(8, "Kamida 8 belgi"),
z.regex(/\d/, "Kamida bitta raqam"),
),
});
export default function App() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
resolver: standardResolver(Account),
criteriaMode: "all",
defaultValues: { password: "" },
});
const messages = Object.values(errors.password?.types ?? {});
return (
<form noValidate onSubmit={handleSubmit(() => console.log("ok"))}>
<p>
<label htmlFor="password">Parol</label>
<input
id="password"
type="password"
{...register("password")}
/>
</p>
<ul>
{messages.map((m) => (
<li key={m}>{m}</li>
))}
</ul>
<button>Yuborish</button>
</form>
);
}Ekranda:
Parol
Kamida 8 belgi
Kamida bitta raqam
YuborishMehmon bir vaqtda ikkala talabni ko'radi — birini tuzatib, yana yuborib, ikkinchisini bilishi shart emas. Parol misoli — faqat qoidalar uchun; parol maydoni qoralamaga yozilmaydi va konsolga chiqarilmaydi (RHF III).
9. Real ishda
- Ish e'lonlarida ko'pincha "React Hook Form + Zod" yoziladi; Formik va Yup — eski loyihalar uchun. Ikkalasini o'qiy olish — afzallik.
- Next.js loyihalari — server action'lar bilan Conform yoki React'ning
useActionStatei (Server Actions II); RHF ham ishlatiladi, lekin u holda forma JavaScript'ga tayanadi. - Kutubxona tanlash — Paket tanlash va baholash darsidagi mezonlar: hajm (o'lchang!), yangilanish tezligi, yuklab olishlar, TypeScript, jamoa tajribasi.
- Intervyu savollari: "RHF va Formik farqi?", "Standard Schema nima?", "nega Valibot kichik?", "JavaScript'siz ishlaydigan forma qanday quriladi?".
Xulosa
- Forma kutubxonasi va sxema kutubxonasi — alohida tanlov; Standard Schema (
~standard.validate) ularni bog'laydi. - O'lchov (gzip, React bilan):
<form action>72.2, Formik 84.2, RHF 84.6, TanStack Form 88.3, Conform 93.7 KB. Sxema: Zod 23.7,zod/mini5.8, Valibot 1.6 KB. - Formik — controlled, eski loyihalar; TanStack Form — to'liq type-safe; Conform — server action, JavaScript'siz ishlaydi.
- Valibot — eng kichik (funksiyalar +
pipe), ArkType — tur-satr sintaksisi, Yup — eski, Formik juftligi. vazifalar— RHF +zod/mini: o'lchangan, sabablari yozilgan qaror; tezkor forma — kutubxonasiz.
Keyingi dars: Maxsus inputlar: telefon, sana, OTP, raqam va combobox — +998 telefon maskasi, OTP kod, sana va so'm formatlash, ARIA combobox; vazifalar ga teg combobox'i.
Manbalar
- Standard Schema — standardschema.dev (spetsifikatsiya v1)
- Formik — formik.org/docs (2.4.9); TanStack Form — tanstack.com/form/latest (1.33.5); Conform — conform.guide (1.21.1)
- Valibot — valibot.dev (1.5.0); ArkType — arktype.io; Yup — github.com/jquense/yup
@hookform/resolvers— github.com/react-hook-form/resolvers (standard-schema, valibot)
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!