React Hook Form — o'rnatish, register, handleSubmit
Muammodan boshlaylik
Ro'yxatdan o'tish formasi: 12 ta maydon. 62-darsdagi controlled usul bilan:
- Bitta katta state obyekti va
handleChange - Har bir maydon uchun xato xabari — yana bir state obyekti
- "Maydonga tegildimi" (touched) — yana bitta
- Yuborilmoqda holati
- Va asosiysi: har bir harfda butun forma qayta render bo'ladi. 12 ta maydon, murakkab komponentlar — telefonda yozish sezilarli sekinlashadi
Bu takroriy kod har bir formada yoziladi. React Hook Form (RHF) — bu muammolarni hal qiluvchi eng mashhur forma kutubxonasi.
O'rnatish
npm install react-hook-form
Hajmi ~10 KB, qo'shimcha bog'liqliklarsiz.
Birinchi forma
import { useForm } from 'react-hook-form';
function Login() {
const { register, handleSubmit } = useForm();
function onSubmit(data) {
console.log(data); // { email: 'ali@mail.uz', parol: '12345678' }
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label htmlFor="email">Email</label>
<input id="email" type="email" {...register('email')} />
<label htmlFor="parol">Parol</label>
<input id="parol" type="password" {...register('parol')} />
<button type="submit">Kirish</button>
</form>
);
}
useState yo'q, onChange yo'q, value yo'q, preventDefault yo'q.
register — maydonni ro'yxatga olish
<input {...register('email')} />
register('email') obyekt qaytaradi:
{
name: 'email',
onChange: ..., // qiymat o'zgarganini RHF ga xabar beradi
onBlur: ..., // maydondan chiqilganini
ref: ..., // DOM elementga havola
}
{...} spread bilan bu xususiyatlar input ga qo'yiladi. RHF qiymatni DOM dan ref orqali o'qiydi — React state da saqlamaydi.
Ichma-ich nomlar
<input {...register('ism')} />
<input {...register('manzil.shahar')} />
<input {...register('manzil.kocha')} />
<input {...register('telefonlar.0')} />
// natija
{
ism: 'Ali',
manzil: { shahar: 'Toshkent', kocha: 'Amir Temur' },
telefonlar: ['+998901234567'],
}
Nuqta — ichma-ich obyekt, raqam — massiv indeksi.
Turli input turlari
<input type="checkbox" {...register('shartlar')} /> // true / false
<input type="checkbox" value="html" {...register('kurslar')} /> // bir xil nom →
<input type="checkbox" value="css" {...register('kurslar')} /> // ['html', 'css']
<input type="radio" value="kuryer" {...register('yetkazish')} />
<input type="radio" value="pochta" {...register('yetkazish')} />
<select {...register('viloyat')}>
<option value="toshkent">Toshkent</option>
<option value="samarqand">Samarqand</option>
</select>
<textarea {...register('izoh')} />
<input type="number" {...register('yosh', { valueAsNumber: true })} /> // son
<input type="date" {...register('sana', { valueAsDate: true })} /> // Date
[!INFO]
valueAsNumber: truebo'lmasa,numberinput ning qiymati string bo'ladi (62-dars). Bo'sh maydonvalueAsNumberbilanNaNberadi — buni validatsiyada hisobga oling (64-dars).
handleSubmit
<form onSubmit={handleSubmit(onSubmit, onError)}>
handleSubmit:
e.preventDefault()ni o'zi chaqiradi- Barcha maydonlarni validatsiya qiladi (64-dars)
- Hammasi to'g'ri bo'lsa —
onSubmit(data)ni chaqiradi - Xato bo'lsa —
onError(errors)ni (ixtiyoriy) chaqiradi va birinchi xatoli maydonga fokus qiladi
onSubmit async bo'lishi mumkin — RHF uni kutadi.
defaultValues
const { register, handleSubmit } = useForm({
defaultValues: {
ism: '',
email: '',
viloyat: 'toshkent',
shartlar: false,
kurslar: [],
},
});
Boshlang'ich qiymatlarni shu yerda bering — input dagi defaultValue da emas. Bu reset() qaysi qiymatlarga qaytishini va isDirty (o'zgartirilganmi) ni to'g'ri hisoblash uchun muhim.
Tahrirlash formasi — serverdan ma'lumot
function ProfilTahrir() {
const { data: profil } = useProfil(); // TanStack Query
const { register, handleSubmit, reset } = useForm();
useEffect(() => {
if (profil) reset(profil); // kelganda formani to'ldirish
}, [profil, reset]);
// ...
}
Yoki values parametri bilan — qiymat o'zgarsa forma avtomatik yangilanadi:
const { register } = useForm({ values: profil });
formState — forma holati
const {
register,
handleSubmit,
formState: { isSubmitting, isDirty, isValid, errors, isSubmitSuccessful },
} = useForm();
| Qiymat | Ma'nosi |
|---|---|
errors |
Har bir maydonning xatolari (64-dars) |
isSubmitting |
onSubmit bajarilmoqda (async bo'lsa — tugaguncha) |
isSubmitSuccessful |
Muvaffaqiyatli yuborildi |
isDirty |
Biror maydon defaultValues dan farq qiladi |
dirtyFields |
Qaysi maydonlar o'zgargan |
touchedFields |
Qaysi maydonlarga tegilgan (blur) |
isValid |
Butun forma to'g'rimi |
async function onSubmit(data) {
await fetch('/api/royxat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
}
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Yuborilmoqda...' : "Ro'yxatdan o'tish"}
</button>
isSubmitting uchun alohida useState kerak emas — onSubmit dan qaytgan Promise tugaguncha true.
[!WARNING]
formState— Proxy: RHF faqat siz o'qigan maydonlarni kuzatadi va faqat ular o'zgarganda render qiladi. Shuning uchunformStatedan kerakli qiymatlarni render paytida destructure qiling:const { errors, isSubmitting } = formState. UniuseEffectichida yoki shartli ravishda o'qisangiz, yangilanishlarni o'tkazib yuborishingiz mumkin.
Boshqa foydali funksiyalar
const { watch, setValue, getValues, reset, setFocus } = useForm();
// watch — qiymatni kuzatish (o'zgarganda render)
const yetkazish = watch('yetkazish');
{yetkazish === 'kuryer' && <input {...register('manzil')} />}
// setValue — dasturiy o'zgartirish
setValue('shahar', 'Toshkent', { shouldValidate: true, shouldDirty: true });
// getValues — renderSiz o'qish
const email = getValues('email');
// reset — boshlang'ich holatga yoki yangi qiymatlarga
reset();
reset({ email: '' });
// setFocus
setFocus('email');
[!TIP]
watchkomponentni har o'zgarishda qayta render qiladi. Faqat bitta maydonni kuzatadigan kichik bola komponentdauseWatch({ control, name: 'yetkazish' })ishlating — shunda faqat o'sha bola render bo'ladi, butun forma emas.
Nima uchun shunday?
Nima uchun React Hook Form qiymatlarni React state da emas, DOM da saqlaydi — bu React ning "controlled" falsafasiga zid emasmi?
Bu ongli tanlov, va u tezlik uchun. Controlled formada har bir harf setState → butun forma komponenti va uning barcha bolalari qayta render. 30 maydonli formada bu har harfda 30 ta komponentni tekshirish degani. RHF esa input larni uncontrolled qoldiradi (29-dars): brauzer qiymatni o'zi saqlaydi, RHF unga ref orqali kerak bo'lganda qaraydi va faqat muhim narsalar (xato paydo bo'ldi, forma yuborildi) o'zgarganda render qiladi. Natijada katta formalarda ham har bir harf — nol React render. Controlled kerak bo'lgan joyda esa (murakkab UI kutubxonalari komponentlari) RHF Controller ni taklif qiladi (66-dars).
Xulosa
Eslab qoling:
useForm()→register,handleSubmit,formState,reset,watch,setValue{...register('nom')}— maydonni ulaydi:name,onChange,onBlur,ref- Ichma-ich nomlar:
'manzil.shahar','telefonlar.0' valueAsNumber,valueAsDate— tur o'zgartirishhandleSubmit(onSubmit)—preventDefault, validatsiya, birinchi xatoga fokusdefaultValues— boshlang'ich qiymatlar; serverdan —reset(data)yokivaluesformState:isSubmitting,isDirty,isValid,errors— render paytida destructure qiling- Qiymatlar DOM da — har harfda render yo'q
Keyingi dars
64-dars: React Hook Form — validation, error xabarlar