6-bo‘lim
Hodisalar
onClick va boshqa ishlovchilar, hodisa obyekti, argument uzatish, preventDefault, ko'tarilish va ishlovchini to'g'ri yozish.
Ushbu bo‘lim mundarijasi
React da hodisa ishlovchisi prop sifatida beriladi:
onClick, onChange, onSubmit.
Birinchi ishlovchi #
import { useState } from "react";
import { chiz, bos, matn } from "./dom-muhit.mjs";
function Tugma() {
const [soni, ozgartir] = useState(0);
function bosildi() {
ozgartir(soni + 1);
}
return <button onClick={bosildi}>Bosildi: {soni}</button>;
}
await chiz(<Tugma />);
console.log(matn("button"));
await bos("button");
console.log(matn("button"));
await bos("button");
console.log(matn("button"));
Bosildi: 0
Bosildi: 1
Bosildi: 2
onClick ga funksiyaning o'zi beriladi, uning natijasi emas.
Farqni yaxshi tushunib oling:
<button onClick={bosildi}> // to'g'ri: funksiya beriladi
<button onClick={bosildi()}> // XATO: funksiya darhol chaqiriladi
Ikkinchi shaklda bosildi() chizish paytida ishlaydi va
uning natijasi (odatda undefined) onClick ga beriladi.
Oqibati: tugmani bosganda hech narsa bo'lmaydi, lekin sahifa ochilishi bilan funksiya bir marta ishlaydi.
Agar u holatni o'zgartirsa, cheksiz sikl boshlanadi: chizish → holat o'zgarishi → qayta chizish → yana chaqiruv. React shunda xato beradi:
Too many re-renders
Argument kerak bo'lsa, funksiyani o'rab bering - buni quyida ko'ramiz.
Argument uzatish #
import { useState } from "react";
import { chiz, bos, matn } from "./dom-muhit.mjs";
function Baholash() {
const [ball, ozgartir] = useState(50);
return (
<div>
<p id="natija">Ball: {ball}</p>
<button id="kam" onClick={() => ozgartir(ball - 10)}>-10</button>
<button id="kop" onClick={() => ozgartir(ball + 10)}>+10</button>
</div>
);
}
await chiz(<Baholash />);
console.log(matn("#natija"));
await bos("#kop");
console.log(matn("#natija"));
await bos("#kam");
await bos("#kam");
console.log(matn("#natija"));
Ball: 50
Ball: 60
Ball: 40
() => ozgartir(ball + 10) - o'rovchi funksiya. U bosilganda
chaqiriladi va ichidagi kodni bajaradi.
Bu "qavs qo'yish" muammosining yechimi: tashqi funksiya darhol yaratiladi, lekin ichkarisi faqat bosilganda ishlaydi.
Hodisa obyekti #
import { chiz, bos } from "./dom-muhit.mjs";
function Korish() {
function bosildi(hodisa) {
console.log("turi:", hodisa.type);
console.log("teg:", hodisa.target.tagName);
console.log("id:", hodisa.target.id);
console.log("ko'tariladi:", hodisa.bubbles);
}
return <button id="tugma" onClick={bosildi}>Bos</button>;
}
await chiz(<Korish />);
await bos("#tugma");
turi: click
teg: BUTTON
id: tugma
ko'tariladi: true
Ishlovchi birinchi argument sifatida hodisa obyektini oladi.
| Xossa | Nima beradi |
|---|---|
type | Hodisa turi |
target | Hodisa kelib chiqqan element |
currentTarget | Ishlovchi qo'yilgan element |
preventDefault() | Odatiy xatti-harakatni bekor qiladi |
stopPropagation() | Ko'tarilishni to'xtatadi |
preventDefault #
import { useState } from "react";
import { chiz, bos, matn } from "./dom-muhit.mjs";
function Forma() {
const [holat, ozgartir] = useState("kutilmoqda");
function yuborildi(hodisa) {
hodisa.preventDefault();
ozgartir("yuborildi, sahifa yangilanmadi");
}
return (
<form onSubmit={yuborildi}>
<button type="submit">Yuborish</button>
<p id="holat">{holat}</p>
</form>
);
}
await chiz(<Forma />);
console.log(matn("#holat"));
await bos("button");
console.log(matn("#holat"));
kutilmoqda
yuborildi, sahifa yangilanmadi
Forma odatda yuborilganda sahifani qayta yuklaydi - bu HTML ning eski xatti-harakati.
React ilovasida bu deyarli hech qachon kerak emas:
preventDefault() uni to'xtatadi.
Ishlovchini <form> ga qo'yish kerak, <button> ga emas:
<form onSubmit={yuborildi}> // to'g'ri
<button onClick={yuborildi}> // to'liq emas
Sabab: foydalanuvchi formani Enter bosib ham yuborishi
mumkin. Bu holda tugma bosilmaydi, lekin submit hodisasi
baribir sodir bo'ladi.
onSubmit ikkala yo'lni ham qamrab oladi va klaviatura bilan
ishlaydiganlar uchun muhim.
Ko'tarilish #
import { chiz, bos } from "./dom-muhit.mjs";
function Ichma() {
const izlar = [];
function tashqi() {
izlar.push("tashqi");
console.log(izlar.join(" -> "));
}
function ichki(hodisa) {
izlar.push("ichki");
}
function toxtatuvchi(hodisa) {
hodisa.stopPropagation();
console.log("faqat ichki (to'xtatildi)");
}
return (
<div onClick={tashqi}>
<button id="oddiy" onClick={ichki}>Oddiy</button>
<button id="toxta" onClick={toxtatuvchi}>To'xtatuvchi</button>
</div>
);
}
await chiz(<Ichma />);
await bos("#oddiy");
await bos("#toxta");
ichki -> tashqi
faqat ichki (to'xtatildi)
Hodisa ichkaridan tashqariga ko'tariladi: avval tugmaning
ishlovchisi, keyin uni o'rab turgan <div> niki.
stopPropagation() bu zanjirni to'xtatadi.
U muammoni hal qilganday tuyuladi, lekin ko'pincha yangisini yaratadi: tashqaridagi kod hodisani umuman ko'rmaydi.
Masalan, "sahifaning istalgan joyiga bosilsa, menyuni yop" degan mantiq buzilib qoladi va sababi darhol ko'rinmaydi.
Ko'pincha yaxshiroq yechim - tashqi ishlovchida tekshirish:
function tashqi(hodisa) {
if (hodisa.target.closest(".ichki")) return;
// ...
}
Shunda hodisa o'z yo'lida davom etadi, siz esa faqat kerakli holatda ish qilasiz.
Ko'p ishlatiladigan hodisalar #
| Prop | Qachon |
|---|---|
onClick | Bosilganda |
onChange | Kiritish o'zgarganda |
onSubmit | Forma yuborilganda |
onKeyDown | Klavisha bosilganda |
onFocus / onBlur | Fokus kelganda / ketganda |
onMouseEnter / onMouseLeave | Sichqoncha ustiga kelganda |
import { useState } from "react";
import { chiz, yoz, matn } from "./dom-muhit.mjs";
function Qidiruv() {
const [so, ozgartir] = useState("");
return (
<div>
<input value={so} onChange={(h) => ozgartir(h.target.value)} />
<p id="natija">
{so === "" ? "hech narsa yozilmadi" : `qidirilmoqda: ${so}`}
</p>
</div>
);
}
await chiz(<Qidiruv />);
console.log(matn("#natija"));
await yoz("input", "react");
console.log(matn("#natija"));
hech narsa yozilmadi
qidirilmoqda: react
onChange React da har bir belgida ishlaydi - HTML dagi
change dan farqli o'laroq, u fokus ketishini kutmaydi.
React har bir element uchun alohida tinglovchi qo'ymaydi. U hodisalarni ildizda tinglaydi va keyin to'g'ri komponentga yo'naltiradi.
Sizga beriladigan hodisa obyekti ham brauzerning asl obyekti emas, balki React ning sintetik o'ramasi. U hamma brauzerda bir xil ishlaydi - eski davrda bu katta muammo edi.
Asl brauzer hodisasi kerak bo'lsa, u hodisa.nativeEvent da
turadi. Amalda bu juda kam kerak bo'ladi.
onClickbilan hisoblagich yozing.onClick={bosildi()}deb yozib, nima bo'lishini ko'ring.- O'rovchi funksiya bilan argument uzating.
- Hodisa obyektidan
typevatargetni chiqaring. - Formada
preventDefault()ishlating. - Ishlovchini tugmaga qo'yib,
Enterbilan sinab ko'ring. - Ichma-ich ishlovchilar bilan ko'tarilishni kuzating.
stopPropagation()qo'shib, farqni ko'ring.onChangebilan kiritishni holatga bog'lang.onMouseEnterbilan ustiga kelishni ushlang.
Xulosa #
- Ishlovchi prop sifatida beriladi:
onClick={funksiya}. - Qavs qo'ymang:
onClick={f()}funksiyani darhol chaqiradi. - Argument kerak bo'lsa - o'rovchi funksiya:
onClick={() => f(x)}. - Ishlovchi hodisa obyektini oladi;
target- hodisa kelib chiqqan element. - Formada
preventDefault()sahifa yangilanishini to'xtatadi. onSubmitni formaga qo'ying -Enterbilan ham ishlaydi.- Hodisa ichkaridan tashqariga ko'tariladi;
stopPropagationni kam ishlating. - React hodisalari sintetik - hamma brauzerda bir xil.
Keyingi bo'limda holatni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.