IlmHamroh
JavaScript Full-stack/18-qism. React chuqur14/42-dars18 daqiqa
Mundarija (27)

React class komponentlar: eski kodni o'qish, lifecycle metodlari va hooklarga ko'chirish

Qisqacha: Class komponent — class X extends Component va render() metodi bor JavaScript klassi. Hooklardan oldin (2019 gacha) React shunday yozilgan, shuning uchun eski loyihalarda ko'p uchraydi. State — this.state obyekti, yangilash — this.setState({…}). U birlashtiradi (merge), useState kabi almashtirmaydi. Props — this.props. Effektlar o'rnida uchta lifecycle metodi bor: componentDidMount (ekranga qo'yildi), componentDidUpdate (yangilandi) va componentWillUnmount (olib tashlanadi) — ularning hammasi useEffect ga to'g'ri keladi. PureComponent — props va state o'zgarmasa qayta chizmaydi (memo ning class versiyasi). Eng ko'p tuzoq — this: metod onClick ga uzatilsa, this yo'qoladi. Yangi kod uchun class kerak emas, faqat bitta istisno — error boundary.

Bu darsda

  • Class komponentni o'qiysiz: render, this.props, this.state, setState va uning birlashtirishi.
  • Lifecycle metodlari qachon chaqirilishini konsolda ko'rasiz va ularni useEffect bilan solishtirasiz.
  • this yo'qolishi tuzog'ini va uning uch davosini bilasiz.
  • PureComponent nima qilishini tushuntira olasiz.
  • Class komponentni hooklarga bosqichma-bosqich ko'chirasiz va vazifalar dagi XatoChegarasi ni boshidan oxirigacha o'qiysiz.

Oldin bilishingiz kerak: class sintaksisi, this yo'qolishi, Effekt hayot sikli, Error boundary.

1. Nega bu kerak?

Sardor birinchi ish kunida 2018-yilda yozilgan buxgalteriya tizimini ochdi. 300 ta komponentning 200 tasi class bilan yozilgan: this.state, componentDidMount, this.handleClick = this.handleClick.bind(this). U hooklarni biladi, lekin bu kodni o'qiy olmadi. Jamoa rahbari: "Yangi kodni hook bilan yoz, lekin eskisini tuzata olishing kerak" dedi.

Bu — real holat. React 2013-yilda chiqqan, hooklar esa 2019-yilda (React 16.8). Olti yil davomida yozilgan millionlab qator kod — class komponentlarda. Kompaniyalar ularni birdaniga qayta yozmaydi. Siz esa ularni o'qiy olishingiz, tuzata olishingiz va kerak bo'lsa hooklarga ko'chira olishingiz kerak.

Ikkinchi sabab — error boundary. Error boundary darsida ko'rdik: u hozircha faqat class bo'la oladi. vazifalar ning XatoChegarasi i — class. Bugun uni har qatorigacha tushunamiz.

Hayotiy o'xshatish: eski uslubdagi qo'lyozma. Bobongizning kundaligi lotin emas, kirill yozuvida, ba'zi so'zlar eskicha. Siz bugun bu yozuvda yozmaysiz, lekin uni o'qiy olsangiz — oila tarixini bilasiz. Class komponent — React'ning "eski yozuvi": yangi kod uchun emas, mavjudini o'qish uchun.

2. Class komponent anatomiyasi

2.1 Bir xil komponent — ikki yozuvda

«Bahor» buyurtma hisoblagichi. Avval tanish funksiya:

jsx
function OrderCounter({ dish }) {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>
      {dish}: {count}
    </button>
  );
}

Endi aynan shu — class:

jsx
import { Component } from "react";

class OrderCounter extends Component {
  state = { count: 0 }; // useState(0) o'rni

  render() {
    return (
      <button
        onClick={() => this.setState({ count: this.state.count + 1 })}
      >
        {this.props.dish}: {this.state.count}
      </button>
    );
  }
}

export default function App() {
  return <OrderCounter dish="Osh" />;
}

Ekranda:

text
Osh: 2

Qatorma-qator moslik:

Class Funksiya
class OrderCounter extends Component function OrderCounter(props)
render() { return …; } funksiyaning return i
this.props.dish { dish } parametri
state = { count: 0 } useState(0)
this.state.count count
this.setState({ count: … }) setCount(…)

extends Component — meros: Component klassi setState va boshqa metodlarni beradi. state = { … } — class maydoni. Eski kodda uning o'rnida konstruktor bo'ladi:

jsx
constructor(props) {
  super(props); // Component'ga props'ni berish — shart
  this.state = { count: 0 };
}

Ikkalasi bir xil ishni qiladi. Konstruktorli yozuv — 2018 gacha, maydonli — keyin.

2.2 setState birlashtiradi

useState bilan obyekt state'ni yangilaganda butun obyektni berish kerak edi (State III). this.setState esa berilgan maydonlarni eski state'ga qo'shadi (birlashtiradi):

jsx
import { Component } from "react";

class BookingForm extends Component {
  state = { name: "", guests: 2 };

  render() {
    console.log("state:", JSON.stringify(this.state));
    return (
      <button onClick={() => this.setState({ name: "Malika" })}>
        Ismni yoz
      </button>
    );
  }
}

export default function App() {
  return <BookingForm />;
}

Konsolda:

text
state: {"name":"","guests":2}
state: {"name":"Malika","guests":2}

guests yo'qolmadi — setState({ name }) faqat name ni almashtirdi. useState da setState({ name: "Malika" }) qilsangiz, guests yo'qolardi. Ko'chirishda shuni unutmang: class'dagi this.setState({ name }) → funksiyada setForm((f) => ({ ...f, name })).

Birlashtirish faqat birinchi darajada: this.setState({ address: { city } }) — address ichidagi boshqa maydonlarni o'chiradi.

setState ham asinxron va partiyalab ishlaydi (State II). Oldingi qiymatga tayansa — updater shakli: this.setState((prev) => ({ count: prev.count + 1 })).

3. this tuzog'i

3.1 Metod uzatilganda

Eski kodda ishlovchilar alohida metod sifatida yoziladi. Shunday:

jsx
import { Component } from "react";

class Counter extends Component {
  state = { count: 0 };

  handleClick() {
    this.setState({ count: this.state.count + 1 }); // this?
  }

  render() {
    return <button onClick={this.handleClick}>+1</button>; // ❌
  }
}

export default function App() {
  return <Counter />;
}

Konsolda:

text
Uncaught TypeError: Cannot read properties of undefined (reading 'setState')
TypeError: Cannot read properties of undefined (reading 'setState')

"undefined ning setState xususiyatini o'qib bo'lmaydi". this — undefined. Sabab — this yo'qolishi: onClick={this.handleClick} metodni obyektdan ajratib, oddiy funksiya sifatida uzatadi. React uni keyin handleClick() deb chaqiradi — nuqtadan oldin obyekt yo'q. Klass ichi esa qat'iy rejimda: this — undefined.

3.2 Uch davo — eski kodda uchalasi ham uchraydi

jsx
// 1) Konstruktorda bind — eng eski
constructor(props) {
  super(props);
  this.handleClick = this.handleClick.bind(this);
}

// 2) Arrow funksiya maydoni — eng ko'p uchraydi
handleClick = () => {
  this.setState({ count: this.state.count + 1 });
};

// 3) JSX ichida arrow — har renderda yangi funksiya
<button onClick={() => this.handleClick()}>+1</button>

Ikkinchisi — XatoChegarasi dagi qaytaUrin = (): void => { … } va Error boundary dagi reset = () => …. Arrow funksiya o'z this ini yaratmaydi, klass maydoni esa har nusxada alohida yaratiladi — this doim shu komponent.

Funksiya komponentlarda bu muammo umuman yo'q — this ning o'zi yo'q. Bu hooklar yaratilishining sabablaridan biri edi.

4. Lifecycle metodlari

4.1 Uch asosiy metod

Class komponentning "hayoti" — ekranga qo'yilish (mount), yangilanish (update) va olib tashlanish (unmount). Har bosqichga metod bor:

jsx
import { Component, useState } from "react";

class PriceTag extends Component {
  componentDidMount() {
    console.log("didMount:", this.props.price);
  }
  componentDidUpdate(prevProps) {
    const { price } = this.props;
    console.log("didUpdate:", prevProps.price, "→", price);
  }
  componentWillUnmount() {
    console.log("willUnmount");
  }
  render() {
    console.log("render:", this.props.price);
    return <p>Osh — {this.props.price} so'm</p>;
  }
}

export default function App() {
  const [price, setPrice] = useState(35000);
  const [show, setShow] = useState(true);
  return (
    <div>
      <button onClick={() => setPrice(38000)}>
        Narxni o'zgartir
      </button>{" "}
      <button onClick={() => setShow(false)}>Yopish</button>
      {show && <PriceTag price={price} />}
    </div>
  );
}

Konsolda:

text
render: 35000
didMount: 35000
render: 38000
didUpdate: 35000 → 38000
willUnmount

Ekranda:

text
Narxni o'zgartir Yopish

Tartib — commit qoidasi bo'yicha: avval render, keyin DOM yangilanadi, keyin did… metodlari. componentDidUpdate oldingi props'ni oladi — qaysi narsa o'zgarganini solishtirish uchun.

stateDiagram-v2
  [*] --> Render1: mount
  Render1 --> DidMount: DOM tayyor
  DidMount --> Render2: props yoki state o'zgardi
  Render2 --> DidUpdate: DOM yangilandi
  DidUpdate --> Render2: yana o'zgardi
  DidUpdate --> WillUnmount: olib tashlanmoqda
  DidMount --> WillUnmount: olib tashlanmoqda
  WillUnmount --> [*]

Diagrammada render ikki joyda: mount va har yangilanishda. did… metodlari doim render'dan keyin. WillUnmount — oxirgi so'z: obunalarni bekor qilish, taymerni to'xtatish.

4.2 Bitta effekt — uch metodga bo'lingan

Class'da bitta "ish" (masalan, obuna) uch joyga tarqaladi. «Bahor» oshxona ekrani — tanlangan stolning buyurtmalariga obuna:

jsx
class TableOrders extends Component {
  componentDidMount() {
    this.unsubscribe = subscribe(this.props.table);
  }
  componentDidUpdate(prevProps) {
    // stol o'zgarsa — eski obunani yopib, yangisini ochish
    if (prevProps.table !== this.props.table) {
      this.unsubscribe();
      this.unsubscribe = subscribe(this.props.table);
    }
  }
  componentWillUnmount() {
    this.unsubscribe();
  }
  render() {
    return <p>{this.props.table}-stol buyurtmalari</p>;
  }
}

Hook bilan — bitta joyda:

jsx
function TableOrders({ table }) {
  useEffect(() => {
    const unsubscribe = subscribe(table);
    return unsubscribe; // cleanup — unmount va table o'zgarganda
  }, [table]);
  return <p>{table}-stol buyurtmalari</p>;
}

componentDidUpdate dagi if — [table] bog'liqligining qo'lda yozilgan shakli. Eski kodda eng ko'p uchraydigan xato aynan shu if ni unutish edi. Unda stol o'zgarganda obuna eski stolda qoladi. Effekt hayot sikli darsidagi "effekt — sinxronlash, mount/unmount emas" g'oyasi aynan shu muammodan tug'ilgan.

4.3 To'liq moslik jadvali

Class Hook
componentDidMount useEffect(fn, [])
componentDidUpdate (+ if bilan solishtirish) useEffect(fn, [bog'liqliklar])
componentWillUnmount useEffect qaytargan cleanup
shouldComponentUpdate memo (memo)
getDerivedStateFromProps renderda hisoblash yoki key (State strukturasi)
getSnapshotBeforeUpdate hook'da o'xshashi yo'q (scroll holatini saqlash uchun kamdan-kam)
static getDerivedStateFromError, componentDidCatch hook'da yo'q — error boundary class bo'lib qoladi
static contextType + this.context use(Context) / useContext
createRef() useRef()

Oxirgi uch qator diqqatga sazovor: ikki metodning hook'dagi o'xshashi yo'q. Shuning uchun ba'zi class'lar (error boundary) bugun ham yoziladi.

Tekshirib ko'ring: Class'da componentDidMount ichida setInterval, lekin componentWillUnmount yo'q. Komponent yopilganda nima bo'ladi?

Javob

Taymer ishlayveradi — komponent yo'q bo'lsa ham. Uning ichida this.setState bo'lsa, React o'chirilgan komponent uchun ogohlantirmaydi ham (React 18 dan), lekin xotira va protsessor isrof bo'ladi. Bu — cleanup'siz effektning class'dagi ko'rinishi. Tuzatish: componentWillUnmount() { clearInterval(this.timer); }, hook'ga ko'chirilsa — useEffect cleanup'i.

5. PureComponent

PureComponent — Component ning varianti: props va state sayoz solishtirilib, o'zgarmagan bo'lsa render chaqirilmaydi:

jsx
import { Component, PureComponent, useState } from "react";

class PlainMenu extends Component {
  render() {
    console.log("Component render");
    return <p>Menyu: {this.props.dish}</p>;
  }
}

class PureMenu extends PureComponent {
  render() {
    console.log("PureComponent render");
    return <p>Menyu: {this.props.dish}</p>;
  }
}

export default function App() {
  const [guests, setGuests] = useState(1);
  return (
    <div>
      <button onClick={() => setGuests(guests + 1)}>+1 mehmon</button>
      <p>Mehmonlar: {guests}</p>
      <PlainMenu dish="Osh" />
      <PureMenu dish="Osh" />
    </div>
  );
}

Konsolda:

text
Component render
PureComponent render
Component render
Component render

Ekranda:

text
+1 mehmon
Mehmonlar: 3
Menyu: Osh
Menyu: Osh

Ota ikki marta qayta chizildi. Oddiy Component har safar chizildi, PureComponent — faqat birinchi marta: dish o'zgarmagan. Funksiyadagi o'xshashi — memo(Menu). Tafsiloti, "sayoz solishtirish" tuzoqlari va qachon kerakligi — memo, useMemo, useCallback darsida.

6. Class'ni hooklarga ko'chirish

6.1 Qadamlar

Eski komponentni ko'chirish — mexanik ish, lekin tartib bilan:

  1. class X extends Component → function X(props) (yoki { … } destrukturizatsiya).
  2. render() ichini funksiya tanasiga ko'chiring, return qoladi.
  3. this.props.x → x.
  4. this.state ning har maydoni — alohida useState (yoki bog'liqlari — bitta obyekt / useReducer).
  5. this.setState({ a }) → setA(…); birlashtirishni unutmang.
  6. Lifecycle'lar → useEffect («To'liq moslik jadvali» bo'yicha), bitta ish — bitta effekt.
  7. Metodlar → oddiy ichki funksiyalar; bind va this yo'qoladi.
  8. Testlar ishlayaptimi — tekshiring.

6.2 Misol: oshxona taymeri

Eski kod (o'qing):

jsx
import { Component } from "react";

class CookingTimer extends Component {
  constructor(props) {
    super(props);
    this.state = { seconds: 0, running: true };
    this.stop = this.stop.bind(this);
  }
  componentDidMount() {
    this.timer = setInterval(() => {
      this.setState((prev) => ({ seconds: prev.seconds + 1 }));
    }, 300);
  }
  componentWillUnmount() {
    clearInterval(this.timer);
  }
  stop() {
    clearInterval(this.timer);
    this.setState({ running: false });
  }
  render() {
    const { seconds, running } = this.state;
    return (
      <div>
        <p>
          {this.props.dish}: {seconds} s {running ? "" : "(to'xtadi)"}
        </p>
        <button onClick={this.stop}>To'xtat</button>
      </div>
    );
  }
}

export default function App() {
  return <CookingTimer dish="Osh" />;
}

Ekranda:

text
Osh: 2 s (to'xtadi)
To'xtat

Taymer har 300 ms da "bir soniya" qo'shadi (tez ko'rinsin deb). 750 ms dan keyin «To'xtat» — 2 da to'xtadi.

Hook bilan — o'sha xulq:

jsx
import { useEffect, useRef, useState } from "react";

function CookingTimer({ dish }) {
  const [seconds, setSeconds] = useState(0);
  const [running, setRunning] = useState(true);
  const timer = useRef(null); // this.timer o'rni

  useEffect(() => {
    timer.current = setInterval(() => {
      setSeconds((s) => s + 1);
    }, 300);
    return () => clearInterval(timer.current); // willUnmount
  }, []);

  function stop() {
    clearInterval(timer.current);
    setRunning(false);
  }

  return (
    <div>
      <p>
        {dish}: {seconds} s {running ? "" : "(to'xtadi)"}
      </p>
      <button onClick={stop}>To'xtat</button>
    </div>
  );
}

export default function App() {
  return <CookingTimer dish="Osh" />;
}

Ekranda:

text
Osh: 2 s (to'xtadi)
To'xtat

Natija bir xil. Moslik: this.state → ikki useState; this.timer → useRef (render chaqirmaydigan xotira — useRef I); componentDidMount + componentWillUnmount → bitta effekt; bind → kerak emas. setState((prev) => …) → setSeconds((s) => s + 1) — updater shakli saqlandi.

6.3 Qachon ko'chirish kerak emas

Hamma eski class'ni qayta yozish — vaqt va xavf. Amaliy qoida:

  • Ishlab turgan, tegilmaydigan kod — qoldiring. "Ishlayapti — tegma".
  • Tez-tez o'zgaradigan kod — o'zgartirish kerak bo'lganda ko'chiring, testlar bilan.
  • Error boundary — class qoladi (yoki react-error-boundary).
  • Yangi kod — faqat funksiya va hooklar.

Class va funksiya komponentlar bir ilovada bemalol aralashadi: class bola funksiya ota ichida, va aksincha.

7. Vazifalar qadami: XatoChegarasi ni o'qish

Bu dars kanonda alohida qadam emas — vazifalar dagi yagona class bilan o'qish mashqi. Error boundary darsida XatoChegarasi.tsx ni ko'rgan edik. Endi uni class nuqtai nazaridan o'qiymiz (TypeScript turlari bilan, kanondan):

tsx
type Holat = { readonly xato: { readonly qiymat: unknown } | null };

export class XatoChegarasi extends Component<Props, Holat> {
  override state: Holat = { xato: null };

  static getDerivedStateFromError(xato: unknown): Holat {
    return { xato: { qiymat: xato } };
  }

  override componentDidCatch(xato: unknown, malumot: ErrorInfo): void {
    this.props.onXato?.(xato, malumot);
  }

  override componentDidUpdate(oldingi: Props): void {
    if (
      this.state.xato !== null &&
      !Object.is(oldingi.tiklashKaliti, this.props.tiklashKaliti)
    ) {
      this.qaytaUrin();
    }
  }

  // Arrow — this doim shu nusxa (fallback'dagi tugmaga uzatiladi)
  qaytaUrin = (): void => {
    this.setState({ xato: null });
  };

  override render(): ReactNode { … }
}

Endi har qatorni bugungi darsdan taniysiz:

Qator Nima
extends Component<Props, Holat> class komponent; TypeScript'da ikki generic — props va state turlari (Generic)
override state: Holat = { … } state — class maydoni; override — "ota klassdagi state ni almashtiryapman" (TS tekshiradi)
static getDerivedStateFromError render bosqichi, sof — hook'da o'xshashi yo'q
componentDidCatch commit'dan keyin — log
componentDidUpdate(oldingi) prevProps bilan solishtirish — «Bitta effekt — uch metodga bo'lingan» dagi if naqshi
qaytaUrin = () => … arrow maydon — this tuzog'ining 2-davosi
this.setState({ xato: null }) birlashtiradi; bu yerda state'da bitta maydon

override kalit so'zi — TypeScript'ning noImplicitOverride sozlamasi talab qiladi: ota klassdagi metodni almashtirsangiz, buni ochiq yozasiz. Ota klassda bunday metod bo'lmasa (masalan, componentDidCatch ni xato yozsangiz), tsc xato beradi (Klasslar TypeScript'da). Kodni o'qish uchun bu shunchaki "ota metodini almashtirish" belgisi.

componentDidUpdate dagi solishtirishni hook'da yozib bo'lmasmidi? Bo'lardi — useEffect(…, [tiklashKaliti]). Lekin chegaraning qolgan ikki metodi class talab qiladi, shuning uchun hammasi bir klassda.

8. Ko'p uchraydigan xatolar

Belgi Sabab Davosi
Cannot read properties of undefined (reading 'setState') metod this siz uzatildi arrow maydon yoki bind
ko'chirgandan keyin state maydonlari yo'qoldi setState birlashtirardi, useState almashtiradi setX((x) => ({ ...x, a })) yoki alohida useState
stol o'zgarganda obuna eskida qoldi componentDidUpdate da if yo'q prevProps bilan solishtirish yoki useEffect(…, [table])
yopilgandan keyin taymer ishlayveradi componentWillUnmount yo'q clearInterval cleanup'da
super(props) siz — this xatosi konstruktorda this dan oldin super chaqirilmagan super(props) birinchi qator
UNSAFE_componentWillMount ogohlantirishi eski lifecycle (StrictMode) componentDidMount / konstruktor

9. Mashqlar

Mashqlar kurs/mashqlar/18/14-class/ da. Har yechimni «Ishga tushir» bilan sinang.

1-mashq (oson): moslik

Class'dagi narsaning hook'dagi o'xshashini yozing:

  • this.state = { count: 0 } →
  • componentWillUnmount → useEffect'ning
  • PureComponent →
  • this.timer (render chaqirmaydigan xotira) →
Yechim
  • useState — const [count, setCount] = useState(0).
  • cleanup — useEffect qaytargan funksiya.
  • memo — props o'zgarmasa qayta chizmaydi.
  • useRef — o'zgarsa ham render chaqirmaydi.

2-mashq (o'rta): this ni tiklang

Tugma bosilganda ilova yiqiladi. handleAdd ni arrow funksiya maydoniga aylantiring — boshqa joyga tegmang. Ishora: «Uch davo» bo'limi.

jsx
import { Component } from "react";

class AddButton extends Component {
  state = { added: 0 };

  handleAdd() {
    this.setState((prev) => ({ added: prev.added + 1 }));
  }

  render() {
    return (
      <div>
        <button onClick={this.handleAdd}>Savatga</button>
        <p>Qo'shildi: {this.state.added}</p>
      </div>
    );
  }
}

export default function App() {
  return <AddButton />;
}

Konsolda:

text
Uncaught TypeError: Cannot read properties of undefined (reading 'setState')
TypeError: Cannot read properties of undefined (reading 'setState')
Yechim
jsx
import { Component } from "react";

class AddButton extends Component {
  state = { added: 0 };

  handleAdd = () => {
    this.setState((prev) => ({ added: prev.added + 1 }));
  };

  render() {
    return (
      <div>
        <button onClick={this.handleAdd}>Savatga</button>
        <p>Qo'shildi: {this.state.added}</p>
      </div>
    );
  }
}

export default function App() {
  return <AddButton />;
}

Ekranda:

text
Savatga
Qo'shildi: 1

handleAdd = () => { … } — class maydoni, arrow funksiya. U this ni yaratilgan joyidan — komponent nusxasidan oladi. onClick ga uzatilsa ham this yo'qolmaydi.

3-mashq (qiyin): hooklarga ko'chiring

Stol tanlagich: tanlangan stol o'zgarsa, "ulandi: N-stol" va "uzildi: M-stol" yoziladi (obuna taqlidi). Class'ni funksiya + hooklarga ko'chiring: bitta useEffect uch lifecycle metodining o'rnini bossin. Konsol chiqishi o'zgarmasin. Ishora: «Bitta effekt — uch metodga bo'lingan» bo'limi.

jsx
import { Component, useState } from "react";

class TableFeed extends Component {
  componentDidMount() {
    console.log(`ulandi: ${this.props.table}-stol`);
  }
  componentDidUpdate(prevProps) {
    if (prevProps.table !== this.props.table) {
      console.log(`uzildi: ${prevProps.table}-stol`);
      console.log(`ulandi: ${this.props.table}-stol`);
    }
  }
  componentWillUnmount() {
    console.log(`uzildi: ${this.props.table}-stol`);
  }
  render() {
    return <p>{this.props.table}-stol buyurtmalari</p>;
  }
}

export default function App() {
  const [table, setTable] = useState(1);
  const [open, setOpen] = useState(true);
  return (
    <div>
      <button onClick={() => setTable(2)}>2-stol</button>{" "}
      <button onClick={() => setOpen(false)}>Yopish</button>
      {open && <TableFeed table={table} />}
    </div>
  );
}

Konsolda:

text
ulandi: 1-stol
uzildi: 1-stol
ulandi: 2-stol
uzildi: 2-stol
Yechim
jsx
import { useEffect, useState } from "react";

function TableFeed({ table }) {
  useEffect(() => {
    console.log(`ulandi: ${table}-stol`);
    return () => console.log(`uzildi: ${table}-stol`);
  }, [table]);
  return <p>{table}-stol buyurtmalari</p>;
}

export default function App() {
  const [table, setTable] = useState(1);
  const [open, setOpen] = useState(true);
  return (
    <div>
      <button onClick={() => setTable(2)}>2-stol</button>{" "}
      <button onClick={() => setOpen(false)}>Yopish</button>
      {open && <TableFeed table={table} />}
    </div>
  );
}

Konsolda:

text
ulandi: 1-stol
uzildi: 1-stol
ulandi: 2-stol
uzildi: 2-stol

Konsol bir xil, kod esa uch metod o'rniga bitta effekt. componentDidUpdate dagi if — [table] ga aylandi. Cleanup'dagi table — closure: u o'sha effekt yaratilgan paytdagi stol, shuning uchun "uzildi: 1-stol" to'g'ri chiqadi. Class'da buning uchun prevProps kerak edi.

4-mashq: Vazifalar qadami

vazifalar da src/komponentlar/XatoChegarasi.tsx ni oching va «Vazifalar qadami» jadvali bo'yicha har metodni toping. Keyin uch savolga javob yozing:

  1. Ro'yxatdagi qator xato tashladi. Metodlar qaysi tartibda chaqiriladi?
  2. Server ro'yxatni yangiladi (tiklashKaliti o'zgardi). Qaysi metod chegarani tiklaydi?
  3. Nega qaytaUrin arrow maydon, componentDidUpdate esa oddiy metod?

Commit yo'q — bu o'qish mashqi.

Yechim
  1. getDerivedStateFromError (render bosqichi, yangi state) → render (fallback) → commit → componentDidCatch (onXato, log). main.tsx dagi onCaughtError ham shu paytda.
  2. componentDidUpdate(oldingi): xato bor va Object.is(oldingi.tiklashKaliti, this.props.tiklashKaliti) — false, demak this.qaytaUrin().
  3. qaytaUrin uzatiladi — fallback funksiyasiga argument bo'lib, u yerdan tugmaning onClick iga. Uzatilgan oddiy metod this ni yo'qotardi («this tuzog'i» bo'limi). componentDidUpdate ni esa React o'zi chegara.componentDidUpdate(…) deb chaqiradi — nuqtadan oldin obyekt bor, this joyida. Ichidagi this.qaytaUrin() ham shu sababli xavfsiz bo'lardi, lekin tugmadagi chaqiruv — yo'q.

10. Real ishda

  • Eski loyihalar — bank, davlat va korporativ tizimlarda 2016–2019 yillardagi React kodi ko'p. Junior dasturchining birinchi vazifalari ko'pincha shu kodda xato tuzatish.
  • Ko'chirish loyihalari — "class'dan hooklarga" migratsiyasi odatda bosqichma-bosqich: yangi kod — hook, tegilgan eski kod — ko'chiriladi. Keyingi dars — React versiyasini yangilash — shu ishning versiya tomoni.
  • Kutubxonalar ichida — ba'zi eski kutubxonalar (va react-error-boundary) ichida class bor.
  • Intervyu savollari: "Class va funksiya komponent farqi?", "lifecycle metodlari qaysi hooklarga mos?", "nega this.handleClick ni bind qilish kerak edi?", "setState va useState setteri farqi?".

Xulosa

  • Class: extends Component, render(), this.props, this.state, this.setState (birlashtiradi, birinchi daraja).
  • Lifecycle: componentDidMount, componentDidUpdate(prevProps), componentWillUnmount — hammasi useEffect (bitta ish — bitta effekt).
  • this tuzog'i: metod uzatilsa yo'qoladi — arrow maydon, bind yoki JSX'da arrow.
  • PureComponent — sayoz solishtirish bilan render'ni o'tkazib yuboradi (memo o'xshashi).
  • Ko'chirish — mexanik qadamlar; error boundary class bo'lib qoladi; yangi kod — faqat hooklar.
  • vazifalar: XatoChegarasi — yagona class; override, static, arrow qaytaUrin.

Keyingi dars: React versiyasini yangilash: 18 dan 19 ga — olib tashlangan API'lar va codemod'lar bilan xavfsiz yangilash.

Manbalar

  • React: Component — react.dev/reference/react/Component (2026-10 holati, React 19.3)
  • React: PureComponent — react.dev/reference/react/PureComponent
  • React: "Migrating from a class to a function" — react.dev/reference/react/Component#alternatives
  • MDN: "Classes" — developer.mozilla.org/docs/Web/JavaScript/Reference/Classes
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
React class komponentlar: eski kodni o'qish, lifecycle metodlari va hooklarga ko'chirish — IlmHamroh