React

State va useState

Props โ€” o'zgarmas ma'lumot edi. Lekin real ilovalarda ma'lumot doimo o'zgaradi: foydalanuvchi tugmani bosadi, formaga yozadi, ro'yxatga element qo'shadi. Vaqt o'tishi bilan o'zgaradigan ma'lumotni React'da state (holat) boshqaradi. Ushbu dars โ€” React'ning yuragi.

State (holat) nima?

State โ€” bu komponentning "xotirasi". Bu โ€” vaqt o'tishi bilan o'zgaradigan va shu o'zgarish ekranda aks etishi kerak bo'lgan ma'lumot. Masalan:

Muhim savol: nega oddiy o'zgaruvchi ishlatmaymiz? Chunki oddiy o'zgaruvchini o'zgartirsak, React bundan xabar topmaydi va ekranni yangilamaydi. Quyidagi kod ishlamaydi:

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

  function bosildi() {
    count = count + 1;
    console.log(count); // konsolda oshadi...
    // ...lekin ekranda O'ZGARMAYDI!
  }

  return <button onClick={bosildi}>{count}</button>;
}

Bu yerda count konsolda oshsa-da, ekran yangilanmaydi. Sababi: React ekranni faqat maxsus signal olganda qayta chizadi. Ana shu signalni state beradi.

useState hook

State bilan ishlash uchun React useState nomli hookdan foydalanadi. Hook โ€” bu use so'zi bilan boshlanadigan maxsus funksiya bo'lib, komponentga React imkoniyatlarini "ulaydi". Avval uni import qilamiz:

import { useState } from "react";

useState boshlang'ich qiymatni argument sifatida oladi va ikki elementli massiv qaytaradi: joriy qiymat va uni o'zgartiruvchi funksiya. Bu massivni destructuring bilan olamiz:

const [count, setCount] = useState(0);

Bu qatorni tahlil qilamiz:

Hook qoidasi: hook'lar (masalan useState) faqat komponentning eng yuqori darajasida chaqirilishi kerak. Ularni if, for yoki oddiy funksiyalar ichida chaqirmang.

Holatni yangilash va re-render

Holatni to'g'ridan-to'g'ri o'zgartirmaymiz. Uning o'rniga yangilovchi funksiyani (setCount) chaqiramiz. Bu funksiya ikki ish qiladi:

  1. Holatning yangi qiymatini saqlaydi;
  2. Komponentni qayta render qiladi (re-render) โ€” ya'ni komponent funksiyasi qaytadan ishga tushib, ekran yangilanadi.

Mana to'g'ri ishlaydigan hisoblagich:

import { useState } from "react";

function Hisoblagich() {
  const [count, setCount] = useState(0);

  function bosildi() {
    setCount(count + 1); // holatni yangilaymiz
  }

  return <button onClick={bosildi}>Bosildi: {count}</button>;
}

Endi tugma bosilganda: setCount yangi qiymatni saqlaydi va React komponentni qaytadan chizadi. Yangi count qiymati ekranda ko'rinadi. Aynan shu โ€” React'ning deklarativ ishlash mexanizmi.

Holatni hech qachon to'g'ridan-to'g'ri o'zgartirmang: count = count + 1 yoki count++ ishlamaydi va xato hisoblanadi. Har doim setCount(...) orqali yangilang.

Hodisalarni qayta ishlash (event handling)

React'da hodisalar (events) JSX atributlari orqali biriktiriladi. Ular camelCaseda yoziladi va qiymat sifatida funksiyani qabul qiladi:

Muhim nozik jihat: funksiyani chaqirmasdan uzatamiz โ€” nomini { } ichida beramiz:

// TO'G'RI โ€” funksiyaning o'zini beramiz
<button onClick={bosildi}>Bosing</button>

// XATO โ€” funksiyani darrov chaqirib yuboramiz
<button onClick={bosildi()}>Bosing</button>

Ikkinchi holatda bosildi() render paytida darhol chaqiriladi โ€” bu noto'g'ri. Agar funksiyaga argument uzatish kerak bo'lsa, uni ochilgan strelka funksiya ichiga o'raymiz:

<button onClick={() => setCount(count + 1)}>+1</button>
<button onClick={() => setCount(0)}>Tozalash</button>
Hodisa funksiyasi hodisa obyektini (event) qabul qiladi: onClick={(e) => console.log(e)}. Undan, masalan, input qiymatini olishda foydalanamiz (keyingi darsda ko'ramiz).

To'liq hisoblagich misoli

Endi bir necha tugmali to'liq hisoblagichni yig'amiz โ€” oshirish, kamaytirish va tozalash:

import { useState } from "react";

function Hisoblagich() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h2>Qiymat: {count}</h2>
      <button onClick={() => setCount(count + 1)}>+1</button>
      <button onClick={() => setCount(count - 1)}>-1</button>
      <button onClick={() => setCount(0)}>Tozalash</button>
    </div>
  );
}

export default Hisoblagich;

Bu komponent to'liq ishlaydi: har bir tugma setCountni chaqiradi, React qayta render qiladi va yangi qiymat <h2>da ko'rinadi.

Oldingi holatga asoslanib yangilash

Agar yangi qiymat eski qiymatga bog'liq bo'lsa (masalan, oshirish), setCountga qiymat o'rniga funksiya berish xavfsizroq. React bu funksiyaga eng so'nggi holatni uzatadi:

// Yaxshiroq usul:
setCount(prev => prev + 1);

// Bir necha marta chaqirsangiz farqi bilinadi:
function ucchiOshir() {
  setCount(prev => prev + 1);
  setCount(prev => prev + 1);
  setCount(prev => prev + 1);
  // count 3 ga oshadi (to'g'ri)
}

Agar setCount(count + 1) ni uch marta yozsangiz, natija kutilganidek bo'lmaydi โ€” chunki count bitta render davomida o'zgarmaydi. Funksiya shaklida (prev => prev + 1) esa har safar eng so'nggi qiymat olinadi.

Eslatma: setCount holatni darhol o'zgartirmaydi. React yangilanishlarni to'plab, so'ng bir marta qayta render qiladi (batching). Shuning uchun yangilashdan keyin darrov countni o'qisangiz, eski qiymatni ko'rasiz.

Xulosa