useState — state nima, qanday ishlaydi, re-render tushunchasi

~20 daq · React · Hooks — Asosiy

State nima?

Komponent ba'zan ma'lumotni o'zida saqlashi kerak bo'ladi — tugma bosilganmi, input da nima yozilgan, modal ochiqmi. Bu ma'lumot vaqt o'tishi bilan o'zgaradi va o'zgarganda ekran yangilanishi kerak.

Oddiy o'zgaruvchi bu ishni qila olmaydi:

function Hisoblagich() {
  let son = 0;  // oddiy o'zgaruvchi

  return (
    <div>
      <p>{son}</p>
      <button onClick={() => son++}>+1</button>
    </div>
  );
}

Tugmani bossangiz — son o'zgaradi, lekin ekran yangilanmaydi. Nima uchun? React bu o'zgaruvchi o'zgarganini bilmaydi. Qayta chizish kerakligini bilmaydi.

State — React biladigan o'zgaruvchi. State o'zgarganda React avtomatik komponentni qayta chizadi.


useState qanday ishlatiladi?

import { useState } from 'react';

function Hisoblagich() {
  const [son, setSon] = useState(0);

  return (
    <div>
      <p>{son}</p>
      <button onClick={() => setSon(son + 1)}>+1</button>
    </div>
  );
}

useState(0) ikki narsa qaytaradi: hozirgi qiymat va uni o'zgartiruvchi funksiya. 0 — boshlang'ich qiymat.

const [son, setSon] = useState(0);
       │     │
       │     └── o'zgartiruvchi funksiya
       └── hozirgi qiymat (boshlang'ich: 0)

setSon(yangiQiymat) chaqirilganda — React state ni yangilaydi va komponentni qayta chizadi.


Re-render qanday ishlaydi?

┌─────────────────────────────────────────┐
│  1. Birinchi chizish (mount)            │
│     useState(0) → son = 0              │
│     Ekran: "0"                          │
└──────────────────┬──────────────────────┘
                   │ tugma bosildi
                   ▼
┌─────────────────────────────────────────┐
│  2. setSon(1) chaqirildi               │
│     React: "state o'zgardi!"           │
│     Komponentni qayta ishga tushiradi  │
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  3. Qayta chizish (re-render)           │
│     useState → son = 1  (eslab qoldi)  │
│     Ekran: "1"                          │
└─────────────────────────────────────────┘

Muhim: React komponentni qayta chizganda — butun funksiya qaytadan ishlaydi. useState esa oldingi qiymatni "eslab" qaytaradi.


Bir nechta state

Bir komponentda bir nechta state bo'lishi mumkin:

function Forma() {
  const [ism, setIsm] = useState('');
  const [yosh, setYosh] = useState(0);
  const [xato, setXato] = useState(null);

  function yuborish() {
    if (!ism) {
      setXato('Ism kiritilmadi');
      return;
    }
    setXato(null);
    console.log({ ism, yosh });
  }

  return (
    <div>
      {xato && <p className="xato">{xato}</p>}
      <input value={ism} onChange={e => setIsm(e.target.value)} />
      <input value={yosh} onChange={e => setYosh(+e.target.value)} type="number" />
      <button onClick={yuborish}>Yuborish</button>
    </div>
  );
}

State yangilash — to'g'ri usul

Yangi qiymat hozirgi qiymatga bog'liq bo'lsa — funksiya shakli ishlatiladi:

// ❌ Ba'zan noto'g'ri natija beradi
setSon(son + 1);

// ✅ Har doim to'g'ri — eng so'nggi qiymatni oladi
setSon(prev => prev + 1);

Farqi qachon ko'rinadi? Bir event ichida ikki marta chaqirilganda:

// Tugma bir marta bosilganda natija necha bo'ladi?

// ❌ Natija: 1 (son ikki marta ham 0 edi)
onClick={() => {
  setSon(son + 1);
  setSon(son + 1);
}}

// ✅ Natija: 2
onClick={() => {
  setSon(prev => prev + 1);
  setSon(prev => prev + 1);
}}

Tez-tez uchraydigan xatolar

State ni to'g'ridan-to'g'ri o'zgartirish:

const [users, setUsers] = useState([]);

// ❌ React bu o'zgarishni bilmaydi, ekran yangilanmaydi
users.push({ id: 1, ism: 'Ali' });

// ✅ Yangi massiv yaratib berish
setUsers([...users, { id: 1, ism: 'Ali' }]);

State yangilanishi darhol emas:

function bosish() {
  setSon(son + 1);
  console.log(son); // hali eski qiymat chiqadi!
}

setSon chaqirilgandan keyin son darhol yangilanmaydi. Yangi qiymat keyingi render da bo'ladi. Bu asinxron xulq — React bir nechta yangilanishni birlashtiradi, keyin bir marta qayta chizadi.


Xulosa

useState(boshlangich)
    │
    ├── qiymat    → JSX da ko'rsatiladi
    └── setFn()   → chaqirilganda re-render bo'ladi
  • Oddiy o'zgaruvchi emas — useState ishlatiladi
  • set funksiyasi chaqirilganda React qayta chizadi
  • Hozirgi qiymatga asoslanib yangilashda prev => ... shakli
  • State ni to'g'ridan-to'g'ri o'zgartirmang — yangi qiymat bering

Keyingi dars

9-dars: useState — ob'ekt va massiv state, nima uchun spread kerak