HTML forma bilan ishlash — onSubmit, preventDefault
Muammodan boshlaylik
Login formasi:
function Login() {
const [email, setEmail] = useState('');
const [parol, setParol] = useState('');
function kirish() {
console.log(email, parol);
}
return (
<div>
<input value={email} onChange={(e) => setEmail(e.target.value)} />
<input type="password" value={parol} onChange={(e) => setParol(e.target.value)} />
<button onClick={kirish}>Kirish</button>
</div>
);
}
Ishlaydi... deyarli:
- Parolni yozib Enter bosasiz — hech narsa bo'lmaydi
- Brauzer parol menejeri parolni saqlashni taklif qilmaydi
- Ekran o'quvchi "forma" ni ko'rmaydi
required,type="email"kabi brauzer tekshiruvlari ishlamaydi
Sabab: <form> yo'q. React da ham HTML formalari (HTML kursi, 15-dars) ning barcha qoidalari amal qiladi — faqat ma'lumot yuborishni biz boshqaramiz.
onSubmit va preventDefault
function Login() {
const [email, setEmail] = useState('');
const [parol, setParol] = useState('');
function handleSubmit(e) {
e.preventDefault(); // sahifa yangilanmasin
console.log({ email, parol });
}
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email">Email</label>
<input
id="email"
type="email"
autoComplete="email"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<label htmlFor="parol">Parol</label>
<input
id="parol"
type="password"
autoComplete="current-password"
required
minLength={8}
value={parol}
onChange={(e) => setParol(e.target.value)}
/>
<button type="submit">Kirish</button>
</form>
);
}
onSubmit—<form>da, tugmadaonClickemas. Tugma bosilganda ham, Enter bosilganda ham ishlaydie.preventDefault()— brauzerning standart xatti-harakatini to'xtatadi: formaniactionmanziliga yuborish va sahifani qayta yuklash. Busiz SPA yangilanadi va butun state yo'qoladirequired,minLength,type="email"— brauzer tekshiruvionSubmitdan oldin ishlaydi; xato bo'lsahandleSubmitchaqirilmaydi
JSX dagi farqlar
| HTML | JSX |
|---|---|
for="email" |
htmlFor="email" |
minlength="8" |
minLength={8} |
autocomplete="email" |
autoComplete="email" |
readonly |
readOnly |
<textarea>matn</textarea> |
<textarea value={matn} /> |
<option selected> |
<select value={tanlangan}> |
Controlled — har bir maydon state da
28-darsdagi controlled yondashuv: har bir input ning qiymati useState da, har harfda yangilanadi.
Ko'p maydonli formada har biri uchun alohida useState noqulay. Bitta obyekt bilan:
function Royxat() {
const [forma, setForma] = useState({
ism: '',
email: '',
yosh: '',
shartlar: false,
});
function handleChange(e) {
const { name, value, type, checked } = e.target;
setForma((oldingi) => ({
...oldingi,
[name]: type === 'checkbox' ? checked : value,
}));
}
function handleSubmit(e) {
e.preventDefault();
console.log(forma);
}
return (
<form onSubmit={handleSubmit}>
<input name="ism" value={forma.ism} onChange={handleChange} />
<input name="email" type="email" value={forma.email} onChange={handleChange} />
<input name="yosh" type="number" value={forma.yosh} onChange={handleChange} />
<label>
<input name="shartlar" type="checkbox" checked={forma.shartlar} onChange={handleChange} />
Shartlarga roziman
</label>
<button type="submit">Ro'yxatdan o'tish</button>
</form>
);
}
nameatributi state dagi kalit bilan bir xil — bittahandleChangehammasiga yetadi[name]: ...— hisoblangan kalit- Checkbox uchun
checked, qolganlari uchunvalue
[!WARNING]
type="number"li input hame.target.valueda string qaytaradi:"25",25emas. Hisob-kitobdan oldinNumber(forma.yosh)qiling yokie.target.valueAsNumberdan foydalaning.
Uncontrolled — FormData bilan
Har harfda state yangilash shart bo'lmasa — qiymatlarni faqat yuborishda olish mumkin (29-dars, uncontrolled):
function Aloqa() {
function handleSubmit(e) {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const malumot = Object.fromEntries(formData);
// { ism: 'Ali', email: 'ali@mail.uz', xabar: '...' }
console.log(malumot);
e.currentTarget.reset(); // formani tozalash
}
return (
<form onSubmit={handleSubmit}>
<input name="ism" required />
<input name="email" type="email" required />
<textarea name="xabar" required />
<button type="submit">Yuborish</button>
</form>
);
}
- State yo'q, har harfda render yo'q
FormDatamaydonlarninamebo'yicha yig'adi (HTML kursi, 15-dars)- Bir nechta checkbox bir xil nom bilan —
formData.getAll('qiziqishlar')
| Controlled | Uncontrolled (FormData) | |
|---|---|---|
| Qiymat qayerda | React state | DOM |
| Har harfda render | ✅ | ❌ |
Darhol tekshirish, formatlash (+998 __ ___) |
✅ Oson | Qiyin |
| Boshqa maydonga bog'liq UI | ✅ Oson | Qiyin |
| Kod | Ko'proq | Kam |
Yuborish holati
function Aloqa() {
const [holat, setHolat] = useState('idle'); // 'idle' | 'yuborilmoqda' | 'yuborildi' | 'xato'
async function handleSubmit(e) {
e.preventDefault();
const form = e.currentTarget;
setHolat('yuborilmoqda');
try {
const j = await fetch('/api/aloqa', {
method: 'POST',
body: new FormData(form),
});
if (!j.ok) throw new Error();
setHolat('yuborildi');
form.reset();
} catch {
setHolat('xato');
}
}
if (holat === 'yuborildi') return <p>Rahmat! Xabaringiz yuborildi.</p>;
return (
<form onSubmit={handleSubmit}>
<fieldset disabled={holat === 'yuborilmoqda'}>
<input name="email" type="email" required />
<textarea name="xabar" required />
<button type="submit">
{holat === 'yuborilmoqda' ? 'Yuborilmoqda...' : 'Yuborish'}
</button>
</fieldset>
{holat === 'xato' && <p role="alert">Xatolik. Qaytadan urinib ko'ring.</p>}
</form>
);
}
<fieldset disabled>— yuborilayotganda barcha maydonlarni bir yo'la o'chiradi; ikki marta yuborishning oldini oladie.currentTargetniawaitdan oldin o'zgaruvchiga saqlang — keyin unullbo'lishi mumkinrole="alert"— xato ekran o'quvchiga darhol o'qiladi
[!TIP] React 19 da
<form action={funksiya}>vauseActionState,useFormStatushook lari paydo bo'ldi — ular yuborish holatini avtomatik boshqaradi va ayniqsa Server Actions (Next.js) bilan qulay. Oddiy SPA da yuqoridagionSubmitusuli ham, React Hook Form (keyingi dars) ham to'liq mos.
Nima uchun shunday?
Nima uchun React da <form> ishlatish kerak — hamma narsani onClick va state bilan qilsa bo'ladi-ku?
Bo'ladi — lekin brauzer bepul beradigan narsalarni yo'qotasiz va ularni qo'lda qayta yozishga majbur bo'lasiz. <form> — bu shunchaki o'ram emas, brauzerga "bu maydonlar birga, bular yuboriladigan ma'lumot" degan semantik signal. Shu signal tufayli Enter bilan yuborish, parol menejerlari, avtoto'ldirish, brauzer validatsiyasi, telefonda "Keyingi/Yuborish" tugmalari va ekran o'quvchilarda forma navigatsiyasi ishlaydi. React bu mexanizmni almashtirmaydi — u faqat oxirgi qadamni (sahifa qayta yuklanishini) preventDefault bilan to'xtatib, ma'lumot yuborishni sizga topshiradi.
Xulosa
Eslab qoling:
- Har doim
<form onSubmit>— tugmadaonClickemas; Enter ham ishlaydi e.preventDefault()— sahifa qayta yuklanmasin<button type="submit">; JSX dahtmlFor,minLength,autoComplete- Brauzer validatsiyasi (
required,type)onSubmitdan oldin ishlaydi - Controlled: bitta state obyekti +
namebo'yicha bittahandleChange - Uncontrolled:
Object.fromEntries(new FormData(e.currentTarget)) numberinput qiymati — string- Yuborishda: holat,
<fieldset disabled>,role="alert"bilan xato
Keyingi dars
63-dars: React Hook Form — o'rnatish, register, handleSubmit