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.

🕑 11 daqiqa o‘qish 📄 660 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. useState
  2. Holat - surat
  3. Yangilovchi funksiya
  4. Obyektni yangilash
  5. Massivni yangilash
  6. Bir nechta holat
  7. Dangasa boshlang'ich qiymat
  8. Xulosa

Holat - komponent eslab qoladigan va o'zgarganda qayta chizilishiga sabab bo'ladigan ma'lumot.

useState #

JSX
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"));
Natija
Soni: 0
Soni: 3

useState ikki elementli massiv qaytaradi:

  1. Joriy qiymat;
  2. Uni o'zgartiradigan funksiya.

Argument - boshlang'ich qiymat; u faqat birinchi chizishda ishlatiladi.

Nega oddiy o'zgaruvchi yaramaydi

Mantiqiy savol: nega shunchaki let soni = 0 yozmaymiz?

Ikki sabab bor:

  1. React qayta chizmaydi. Oddiy o'zgaruvchini o'zgartirsangiz, React bundan xabar topmaydi va ekran eski holicha qoladi.
  2. Qiymat yo'qoladi. Komponent har qayta chizilganda funksiya boshidan ishlaydi - let soni = 0 yana noldan boshlanadi.

useState ikkala muammoni ham hal qiladi: qiymat chizishlar orasida saqlanadi, o'zgartirilganda esa React qayta chizadi.

Holat - surat #

JSX
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"));
Natija
uch marta chaqirilgandan keyin: Soni: 1

Uch marta oshirildi, lekin natija 1.

Holat o'zgaruvchisi chizish davomida o'zgarmaydi

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:

JSX
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 #

JSX
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"));
Natija
yangilovchi funksiya bilan: Soni: 3

Endi natija 3.

Funksiya bergan yangilovchi navbatga qo'yiladi va har biri oldingi natijani oladi - suratni emas.

ShaklQachon 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 #

JSX
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"));
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.

Holatni joyida o'zgartirmang

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:

JSX
ozgartir({ ...odam, yosh: odam.yosh + 1 });

Ichma-ich obyektlarda har bir qavatni nusxalash kerak:

JSX
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 #

JSX
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"));
Natija
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.

AmalO'zgartiradi (yomon)Yangi yaratadi (yaxshi)
Qo'shishpush, unshift[...massiv, yangi]
O'chirishpop, splicefilter, slice
Almashtirishmassiv[i] = xmap
Saralashsort, reversetoSorted, toReversed

Bir nechta holat #

JSX
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"));
Natija
Kutilmoqda
Kutilmoqda
Qabul qilindi: Nodira

Bir komponentda istalgancha useState bo'lishi mumkin.

Bog'liq bo'lmagan holatni ajrating

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 #

JSX
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);
Natija
to'g'ridan-to'g'ri chaqirilganda: 3
dangasa berilganda: 1
useState(ogirHisob()) har chizishda ishlaydi

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.

Amaliy topshiriq
  1. useState bilan hisoblagich yozing.
  2. Oddiy let bilan sinab, ekran yangilanmasligini ko'ring.
  3. ozgartir(soni + 1) ni uch marta chaqirib, natijani kuzating.
  4. Uni yangilovchi funksiyaga o'tkazing.
  5. Obyekt holatini ... bilan yangilang.
  6. Obyektni joyida o'zgartirib, ekran qotib qolishini ko'ring.
  7. Massivga push qilib, xuddi shu natijani oling.
  8. [...massiv, yangi] bilan to'g'rilang.
  9. Ikki mustaqil holatni alohida saqlang.
  10. Og'ir boshlang'ich qiymatni dangasa shaklga o'tkazing.

Xulosa #

  • useState joriy 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.

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.