15-bo‘lim
O'z ilgaklaringiz
Ilgaklar qoidalari, takrorlanuvchi mantiqni ilgakka ajratish, holat ulashilmasligi va foydali ilgaklar to'plami.
Ushbu bo‘lim mundarijasi
Ilgak (hook) - nomi use bilan boshlanadigan funksiya. U
boshqa ilgaklarni chaqira oladi.
O'z ilgagingizni yozish - React dagi qayta ishlatishning asosiy usuli.
Ilgaklar qoidalari #
1. Ilgaklarni faqat eng yuqori darajada chaqiring.
Shart, sikl yoki ichma-ich funksiya ichida emas:
if (shart) {
const [x, y] = useState(0); // XATO
}
for (const a of royxat) {
useEffect(...); // XATO
}
2. Ilgaklarni faqat React funksiyalaridan chaqiring.
Komponentdan yoki boshqa ilgakdan - oddiy funksiyadan emas.
Nima uchun. React ilgaklarni nom bilan emas, tartib
raqami bilan eslab qoladi: birinchi useState, ikkinchi
useState va hokazo.
Shart ichida bo'lsa, tartib chizishdan chizishga o'zgaradi va React qiymatlarni aralashtirib yuboradi: bir chizishda birinchi holat, keyingisida boshqasi.
Shuning uchun qoida qat'iy. eslint-plugin-react-hooks uni
avtomatik tekshiradi - uni albatta o'rnating.
Shart kerak bo'lsa, uni ilgak ichiga qo'ying:
useEffect(() => {
if (!shart) return;
// ...
}, [shart]);
Takrorlanuvchi mantiq #
Ikki komponentda bir xil kod bo'lsa, u ilgakka ajratiladi:
import { useState, useCallback } from "react";
export function useAlmashtirgich(boshlangich = false) {
const [ochiq, ozgartir] = useState(boshlangich);
const almashtir = useCallback(() => ozgartir((o) => !o), []);
const yop = useCallback(() => ozgartir(false), []);
const och = useCallback(() => ozgartir(true), []);
return { ochiq, almashtir, yop, och };
}
import { useAlmashtirgich } from "./use-almashtirgich.mjs";
import { chiz, bos, matn } from "./dom-muhit.mjs";
function Menyu() {
const { ochiq, almashtir } = useAlmashtirgich();
return (
<div>
<button id="menyu" onClick={almashtir}>Menyu</button>
<p id="menyu-holat">{ochiq ? "ochiq" : "yopiq"}</p>
</div>
);
}
function Oyna() {
const { ochiq, och, yop } = useAlmashtirgich(true);
return (
<div>
<button id="och" onClick={och}>Ochish</button>
<button id="yop" onClick={yop}>Yopish</button>
<p id="oyna-holat">{ochiq ? "ochiq" : "yopiq"}</p>
</div>
);
}
await chiz(<div><Menyu /><Oyna /></div>);
console.log("menyu:", matn("#menyu-holat"), "| oyna:", matn("#oyna-holat"));
await bos("#menyu");
console.log("menyu bosildi:", matn("#menyu-holat"),
"| oyna:", matn("#oyna-holat"));
await bos("#yop");
console.log("oyna yopildi:", matn("#menyu-holat"),
"| oyna:", matn("#oyna-holat"));
menyu: yopiq | oyna: ochiq
menyu bosildi: ochiq | oyna: ochiq
oyna yopildi: ochiq | oyna: yopiq
Ikki komponent bir xil ilgakni ishlatadi, lekin ularning holati mutlaqo mustaqil.
Bu eng ko'p chalkashtiriladigan nuqta.
useAlmashtirgich chaqirilgan har bir joyda yangi
useState yaratiladi. Ya'ni ilgak - bu retsept, umumiy
ombor emas.
Yuqorida buni ko'rdik: menyu ochilganda oyna o'zgarmadi.
Holat haqiqatan ulashilishi kerak bo'lsa, uni yuqoriga ko'tarish (9-bo'lim) yoki kontekstga qo'yish (13-bo'lim) kerak.
Ma'lumot oluvchi ilgak #
import { useState, useEffect } from "react";
export function useSorov(manzil) {
const [holat, ozgartir] = useState({
malumot: null,
yuklanmoqda: true,
xato: null,
});
useEffect(() => {
let bekor = false;
ozgartir({ malumot: null, yuklanmoqda: true, xato: null });
fetch(manzil)
.then((javob) => {
if (!javob.ok) throw new Error(`holat ${javob.status}`);
return javob.json();
})
.then((malumot) => {
if (!bekor) {
ozgartir({
malumot,
yuklanmoqda: false,
xato: null,
});
}
})
.catch((x) => {
if (!bekor) {
ozgartir({ malumot: null, yuklanmoqda: false,
xato: x.message });
}
});
return () => { bekor = true; };
}, [manzil]);
return holat;
}
import { createServer } from "node:http";
import { useSorov } from "./use-sorov.mjs";
import { chiz, kut, matn } from "./dom-muhit.mjs";
const server = createServer((sorov, javob) => {
if (sorov.url === "/yoq") {
javob.writeHead(404).end("{}");
return;
}
javob.writeHead(200, { "Content-Type": "application/json" });
javob.end(JSON.stringify({ ism: "Malika" }));
});
server.listen(0);
const asos = `http://localhost:${server.address().port}`;
function Profil({ manzil }) {
const { malumot, yuklanmoqda, xato } = useSorov(manzil);
if (yuklanmoqda) return <p id="holat">yuklanmoqda</p>;
if (xato) return <p id="holat">xato: {xato}</p>;
return <p id="holat">salom, {malumot.ism}</p>;
}
await chiz(<Profil manzil={`${asos}/bor`} />);
console.log(matn("#holat"));
await kut();
console.log(matn("#holat"));
await chiz(<Profil key="2" manzil={`${asos}/yoq`} />);
await kut();
console.log(matn("#holat"));
server.close();
yuklanmoqda
salom, Malika
xato: holat 404
11-bo'limdagi butun mantiq endi bitta qatorga sig'di:
const { malumot, yuklanmoqda, xato } = useSorov(manzil);
Har bir komponentda uchta useState va bitta useEffect yozish
kerak emas.
Qiymat o'zgarishini kechiktirish #
import { useState, useEffect } from "react";
export function useKechiktir(qiymat, kechikish = 300) {
const [kechikkan, ozgartir] = useState(qiymat);
useEffect(() => {
const id = setTimeout(() => ozgartir(qiymat), kechikish);
return () => clearTimeout(id);
}, [qiymat, kechikish]);
return kechikkan;
}
import { useState } from "react";
import { useKechiktir } from "./use-kechiktir.mjs";
import { chiz, yoz, kut, matn } from "./dom-muhit.mjs";
const sorovlar = [];
function Qidiruv() {
const [so, ozgartir] = useState("");
const kechikkan = useKechiktir(so, 50);
if (kechikkan !== "") sorovlar.push(kechikkan);
return (
<div>
<input value={so} onChange={(h) => ozgartir(h.target.value)} />
<p id="holat">yozilgan: "{so}", so'rov: "{kechikkan}"</p>
</div>
);
}
await chiz(<Qidiruv />);
await yoz("input", "r");
await yoz("input", "re");
await yoz("input", "rea");
console.log("tez yozilganda:", matn("#holat"));
await kut(120);
console.log("kutilgandan keyin:", matn("#holat"));
console.log("yuborilgan so'rovlar:", sorovlar.join(", "));
tez yozilganda: yozilgan: "rea", so'rov: ""
kutilgandan keyin: yozilgan: "rea", so'rov: "rea"
yuborilgan so'rovlar: rea
Uch marta yozildi, lekin so'rov bittagina bo'ldi.
useKechiktir foydalanuvchi to'xtaguncha kutadi - qidiruv
maydonlarida bu server yukini sezilarli kamaytiradi.
Tozalovchi funksiya eski taymerni bekor qiladi (10-bo'lim), shu sababdan oraliq qiymatlar umuman o'tmaydi.
Foydali ilgaklar #
| Ilgak | Nima qiladi |
|---|---|
useAlmashtirgich | Ochiq/yopiq holat |
useSorov | Ma'lumot olish |
useKechiktir | Tez o'zgarishni kechiktirish |
useMahalliySaqlash | Brauzer xotirasiga saqlash |
useOldingi | Oldingi qiymatni eslash (12-bo'lim) |
Uch belgi:
- Takrorlanish - bir xil
useState+useEffectjuftligi ikki joyda uchrasa. - Nom topilsa - mantiqqa yaxshi nom bera olsangiz, u mustaqil tushuncha.
- Sinash kerak bo'lsa - ilgakni alohida sinash komponentni sinashdan osonroq.
Teskarisi ham to'g'ri: bitta joyda ishlatiladigan uch qatorlik mantiqni ilgakka chiqarish foyda bermaydi - u faqat kodni ikki faylga bo'ladi.
Va yodda tuting: ilgak nomi use bilan boshlanishi shart.
Aks holda eslint uni ilgak deb tanimaydi va qoidalarni
tekshirmaydi.
useStateni shart ichiga qo'yib, xatoni ko'ring.useAlmashtirgichilgagini yozing.- Uni ikki komponentda ishlatib, holat mustaqilligini isbotlang.
- Ma'lumot oluvchi ilgak yozing.
- Uni ikki xil manzil bilan ishlating.
- Kechiktiruvchi ilgak yozing.
- Tez yozib, so'rovlar soni kamayganini ko'ring.
- Tozalovchini olib tashlab, farqni ko'ring.
- Nomi
usebilan boshlanmaydigan ilgak yozib ko'ring. - Bitta joyda ishlatiladigan mantiqni ilgakka chiqarmang.
Xulosa #
- Ilgak - nomi
usebilan boshlanadigan funksiya. - Ikki qoida: faqat eng yuqori darajada va faqat React funksiyalaridan.
- Sabab - React ilgaklarni tartib bo'yicha eslab qoladi.
- Ilgak mantiqni ulashadi, holatni emas - har chaqiruv o'z holatini oladi.
- Takrorlanuvchi
useState+useEffectjuftligi - ilgakka ajratish belgisi. - Bitta joyda ishlatiladigan qisqa mantiqni ajratmang.
Keyingi bo'limda kompozitsiya naqshlarini 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.