7-bo‘lim
Holat - useState
useState bilan holat saqlash, holat suratdek ishlashi, yangilovchi funksiya, obyekt va massivni o'zgarmas yangilash hamda dangasa boshlang'ich qiymat.
Ushbu bo‘lim mundarijasi
Holat - komponent eslab qoladigan va o'zgarganda qayta chizilishiga sabab bo'ladigan ma'lumot.
useState #
import { useState } from "react";
import { chiz, bos, matn } from "./dom-muhit.mjs";
function Hisoblagich() {
const [soni, soniniOzgartir] = useState(0);
return (
<button onClick={() => soniniOzgartir(soni + 1)}>
Soni: {soni}
</button>
);
}
await chiz(<Hisoblagich />);
console.log(matn("button"));
await bos("button");
await bos("button");
await bos("button");
console.log(matn("button"));
Soni: 0
Soni: 3
useState ikki elementli massiv qaytaradi:
- Joriy qiymat;
- Uni o'zgartiradigan funksiya.
Argument - boshlang'ich qiymat; u faqat birinchi chizishda ishlatiladi.
Mantiqiy savol: nega shunchaki let soni = 0 yozmaymiz?
Ikki sabab bor:
- React qayta chizmaydi. Oddiy o'zgaruvchini o'zgartirsangiz, React bundan xabar topmaydi va ekran eski holicha qoladi.
- Qiymat yo'qoladi. Komponent har qayta chizilganda funksiya
boshidan ishlaydi -
let soni = 0yana noldan boshlanadi.
useState ikkala muammoni ham hal qiladi: qiymat chizishlar
orasida saqlanadi, o'zgartirilganda esa React qayta chizadi.
Holat - surat #
import { useState } from "react";
import { chiz, bos, matn } from "./dom-muhit.mjs";
function Uch() {
const [soni, ozgartir] = useState(0);
function uchMartaOshir() {
ozgartir(soni + 1);
ozgartir(soni + 1);
ozgartir(soni + 1);
}
return <button onClick={uchMartaOshir}>Soni: {soni}</button>;
}
await chiz(<Uch />);
await bos("button");
console.log("uch marta chaqirilgandan keyin:", matn("button"));
uch marta chaqirilgandan keyin: Soni: 1
Uch marta oshirildi, lekin natija 1.
soni - bu shu chizish uchun olingan surat. U 0 edi va
ishlovchi tugagunicha 0 bo'lib qoladi.
Shuning uchun uchala qator ham aslida bir xil ish qildi:
ozgartir(0 + 1); // 1
ozgartir(0 + 1); // 1
ozgartir(0 + 1); // 1
React uchalasini yig'ib, oxirgisini qo'llaydi - natija 1.
Bu xato emas, balki ataylab: agar soni chizish o'rtasida
o'zgarsa, komponent bir xil chizishda ikki xil qiymat ko'rib,
chalkash natija berardi.
Yechim - yangilovchi funksiya, u darhol quyida.
Yangilovchi funksiya #
import { useState } from "react";
import { chiz, bos, matn } from "./dom-muhit.mjs";
function Uch() {
const [soni, ozgartir] = useState(0);
function uchMartaOshir() {
ozgartir((oldingi) => oldingi + 1);
ozgartir((oldingi) => oldingi + 1);
ozgartir((oldingi) => oldingi + 1);
}
return <button onClick={uchMartaOshir}>Soni: {soni}</button>;
}
await chiz(<Uch />);
await bos("button");
console.log("yangilovchi funksiya bilan:", matn("button"));
yangilovchi funksiya bilan: Soni: 3
Endi natija 3.
Funksiya bergan yangilovchi navbatga qo'yiladi va har biri oldingi natijani oladi - suratni emas.
| Shakl | Qachon ishlatish |
|---|---|
ozgartir(qiymat) | Yangi qiymat eskisiga bog'liq emas |
ozgartir((oldingi) => ...) | Yangi qiymat eskisidan hisoblanadi |
Qoida: yangi qiymat eskisiga bog'liq bo'lsa, doim funksiya shakli.
Obyektni yangilash #
import { useState } from "react";
import { chiz, bos, matn } from "./dom-muhit.mjs";
function Profil() {
const [odam, ozgartir] = useState({ ism: "Malika", yosh: 20 });
function yoshniOshir() {
ozgartir({ ...odam, yosh: odam.yosh + 1 });
}
function yomonUsul() {
odam.yosh = 99;
ozgartir(odam);
}
return (
<div>
<p id="natija">{odam.ism}, {odam.yosh} yosh</p>
<button id="yaxshi" onClick={yoshniOshir}>To'g'ri</button>
<button id="yomon" onClick={yomonUsul}>Noto'g'ri</button>
</div>
);
}
await chiz(<Profil />);
console.log(matn("#natija"));
await bos("#yaxshi");
console.log("nusxa bilan:", matn("#natija"));
await bos("#yomon");
console.log("o'zgartirish bilan:", matn("#natija"));
Malika, 20 yosh
nusxa bilan: Malika, 21 yosh
o'zgartirish bilan: Malika, 21 yosh
Uchinchi qatorga e'tibor bering: yomonUsul yoshni 99 qildi,
lekin ekran o'zgarmadi.
React yangi holat eskisidan farq qiladimi deb tekshiradi va
buni Object.is bilan qiladi - ya'ni havolani solishtiradi.
odam.yosh = 99 da obyekt o'sha obyektning o'zi bo'lib
qoladi. React "hech narsa o'zgarmabdi" deb xulosa qiladi va
qayta chizmaydi.
Shuning uchun har doim yangi obyekt yarating:
ozgartir({ ...odam, yosh: odam.yosh + 1 });
Ichma-ich obyektlarda har bir qavatni nusxalash kerak:
ozgartir({
...odam,
manzil: { ...odam.manzil, shahar: "Andijon" },
});
Chuqur tuzilmalar noqulay bo'lib ketsa, ikki yo'l bor: holatni
yassiroq qilish yoki useReducer ga o'tish (14-bo'lim).
Massivni yangilash #
import { useState } from "react";
import { chiz, bos, matn } from "./dom-muhit.mjs";
function Royxat() {
const [vazifalar, ozgartir] = useState(["Birinchi"]);
return (
<div>
<p id="soni">{vazifalar.length} ta: {vazifalar.join(", ")}</p>
<button id="qosh"
onClick={() => ozgartir([...vazifalar, "Yangi"])}>
Qo'shish
</button>
<button id="ochir"
onClick={() => ozgartir(vazifalar.slice(0, -1))}>
O'chirish
</button>
<button id="yomon"
onClick={() => {
vazifalar.push("Yomon");
ozgartir(vazifalar);
}}>
Noto'g'ri
</button>
</div>
);
}
await chiz(<Royxat />);
console.log(matn("#soni"));
await bos("#qosh");
await bos("#qosh");
console.log(matn("#soni"));
await bos("#ochir");
console.log(matn("#soni"));
await bos("#yomon");
console.log("push bilan:", matn("#soni"));
1 ta: Birinchi
3 ta: Birinchi, Yangi, Yangi
2 ta: Birinchi, Yangi
push bilan: 2 ta: Birinchi, Yangi
push ham ishlamadi - xuddi obyektdagi kabi, u massivni joyida
o'zgartiradi.
| Amal | O'zgartiradi (yomon) | Yangi yaratadi (yaxshi) |
|---|---|---|
| Qo'shish | push, unshift | [...massiv, yangi] |
| O'chirish | pop, splice | filter, slice |
| Almashtirish | massiv[i] = x | map |
| Saralash | sort, reverse | toSorted, toReversed |
Bir nechta holat #
import { useState } from "react";
import { chiz, bos, yoz, matn } from "./dom-muhit.mjs";
function Forma() {
const [ism, ismniOzgartir] = useState("");
const [yuborildi, yuborishniOzgartir] = useState(false);
return (
<div>
<input
value={ism}
onChange={(h) => ismniOzgartir(h.target.value)}
/>
<button onClick={() => yuborishniOzgartir(true)}>Yuborish</button>
<p id="holat">
{yuborildi ? `Qabul qilindi: ${ism}` : "Kutilmoqda"}
</p>
</div>
);
}
await chiz(<Forma />);
console.log(matn("#holat"));
await yoz("input", "Nodira");
console.log(matn("#holat"));
await bos("button");
console.log(matn("#holat"));
Kutilmoqda
Kutilmoqda
Qabul qilindi: Nodira
Bir komponentda istalgancha useState bo'lishi mumkin.
Umumiy qoida: birga o'zgaradigan qiymatlar bitta holatda, mustaqil qiymatlar alohida bo'lsin.
Yuqorida ism va yuborildi mustaqil - shuning uchun alohida.
Lekin x va y koordinatalari doim birga o'zgaradi, demak
{ x, y } bitta holat bo'lgani ma'qul.
Ortiqcha ajratish ham yomon: o'nta useState bo'lgan komponentni
o'qish qiyin. Bunday holatda useReducer (14-bo'lim) tozaroq.
Dangasa boshlang'ich qiymat #
import { useState } from "react";
import { chiz, bos, matn } from "./dom-muhit.mjs";
let chaqiruvlar = 0;
function ogirHisob() {
chaqiruvlar += 1;
let jami = 0;
for (let i = 0; i < 1000; i++) jami += i;
return jami;
}
function Yomon() {
const [qiymat, ozgartir] = useState(ogirHisob());
return <button onClick={() => ozgartir(qiymat + 1)}>{qiymat}</button>;
}
await chiz(<Yomon />);
await bos("button");
await bos("button");
console.log("to'g'ridan-to'g'ri chaqirilganda:", chaqiruvlar);
chaqiruvlar = 0;
function Yaxshi() {
const [qiymat, ozgartir] = useState(() => ogirHisob());
return <button onClick={() => ozgartir(qiymat + 1)}>{qiymat}</button>;
}
await chiz(<Yaxshi key="yangi" />);
await bos("button");
await bos("button");
console.log("dangasa berilganda:", chaqiruvlar);
to'g'ridan-to'g'ri chaqirilganda: 3
dangasa berilganda: 1
useState(ogirHisob()) da funksiya har bir chizishda
chaqiriladi - garchi natija faqat birinchi marta ishlatilsa ham.
Yuqorida bu uch marta sodir bo'ldi: bir chizish va ikki bosish.
useState(() => ogirHisob()) esa boshqacha: React funksiyaning
o'zini oladi va uni faqat bir marta chaqiradi.
Farq faqat og'ir hisobda sezilarli - masalan,
localStorage dan o'qish yoki katta massivni tayyorlashda.
useStatebilan hisoblagich yozing.- Oddiy
letbilan sinab, ekran yangilanmasligini ko'ring. ozgartir(soni + 1)ni uch marta chaqirib, natijani kuzating.- Uni yangilovchi funksiyaga o'tkazing.
- Obyekt holatini
...bilan yangilang. - Obyektni joyida o'zgartirib, ekran qotib qolishini ko'ring.
- Massivga
pushqilib, xuddi shu natijani oling. [...massiv, yangi]bilan to'g'rilang.- Ikki mustaqil holatni alohida saqlang.
- Og'ir boshlang'ich qiymatni dangasa shaklga o'tkazing.
Xulosa #
useStatejoriy qiymat va o'zgartiruvchi funksiya qaytaradi.- Holat o'zgaruvchisi - chizish uchun olingan surat; ishlovchi ichida o'zgarmaydi.
- Yangi qiymat eskisiga bog'liq bo'lsa - yangilovchi funksiya:
ozgartir((oldingi) => ...). - React havolani solishtiradi: joyida o'zgartirish sezilmaydi.
- Obyekt uchun
{ ...eski }, massiv uchun[...eski],filter,map,toSorted. - Birga o'zgaradigan qiymatlar bitta holatda, mustaqillari alohida.
- Og'ir boshlang'ich qiymatni funksiya sifatida bering.
Keyingi bo'limda formalarni 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.