IlmHamroh
JavaScript Full-stack/18-qism. React chuqur11/42-dars17 daqiqa
Mundarija (30)

React Activity: yashirin UI holatini saqlash, effektlarni to'xtatish va oldindan chizish

Qisqacha: <Activity mode="hidden"> — ichidagi UI'ni o'chirmasdan yashiradi. Shartli chizishda ({open && <Panel />}) yopilgan komponent butunlay yo'qoladi. U bilan state, yozilgan matn va scroll ham ketadi. <Activity> esa uni DOM'da display: none bilan qoldiradi va state'ni saqlaydi. Lekin effektlarini to'xtatadi (cleanup ishlaydi). mode="visible" bo'lganda effektlar qayta ulanadi, ekran esa darhol — qayta yuklashsiz. Boshidanoq hidden bo'lgan Activity'ni React fonda, eng past ustuvorlikda chizib qo'yadi (prerender). Keyingi ekran tayyor turadi — lekin bu ish ham, kod ham pulsiz emas. Activity React 19.2 dan barqaror (import { Activity } from "react").

Bu darsda

  • Tab almashganda state yo'qolishini ko'rasiz va <Activity> bilan uni saqlaysiz.
  • Yashirin holatda effektlar to'xtashini konsolda kuzatasiz va nega bu muhimligini tushuntira olasiz.
  • Oldindan chizish (prerender) qanday ishlashini va qachon zararli ekanini bilasiz.
  • <Activity>, shartli chizish, CSS bilan yashirish va key — to'rtalasini solishtirasiz.
  • vazifalar dagi statistika panelini <Activity> ga o'tkazasiz va nega u birinchi ochilishdan keyin qurilishini tushunasiz.

Oldin bilishingiz kerak: State'ning saqlanishi va key, Effekt hayot sikli, Suspense, lazy.

1. Nega bu kerak?

«Bahor» saytida taom sahifasida uch tab bor: «Tarkibi», «Sharhlar», «Buyurtma». Mehmon «Buyurtma» tabida "piyozsiz, achchiq bo'lsin" deb uzun izoh yozdi. Keyin «Sharhlar» ni ochib, boshqalar nima deganini o'qidi. Qaytib keldi — izoh yo'q. Yana yozishi kerak.

Sardor tablarni shunday yozgan: {tab === "order" && <OrderForm />}. State'ning saqlanishi darsidan bilasiz: komponent daraxtdan olib tashlansa, React uning state'ini ham tashlaydi. Tab yopildi — OrderForm yo'q — izoh yo'q.

Ikkinchi muammo — tezlik. «Sharhlar» tabi har ochilishda serverdan qayta yuklanadi, scroll boshiga qaytadi. Mehmon 30-sharhni o'qiyotgan edi — yana boshidan.

Hayotiy o'xshatish: telefondagi ilovalar. Telegram'dan chiqib, kamerani ochasiz. Telegram yopilmaydi — orqa fonda "uxlaydi". Yozib turgan xabaringiz joyida, chat o'sha joyda. Lekin uxlab yotgan ilova batareyani yemaydi: ovozli qo'ng'iroq, GPS — to'xtatilgan. Qaytsangiz — darhol uyg'onadi. <Activity mode="hidden"> — aynan shu "orqa fon".

2. Muammo: shartli chizish state'ni yo'qotadi

2.1 Tablar — oddiy usulda

jsx
import { useState } from "react";

function OrderForm() {
  const [note, setNote] = useState("");
  return (
    <p>
      <label>
        Izoh{" "}
        <input
          value={note}
          onChange={(e) => setNote(e.target.value)}
        />
      </label>
    </p>
  );
}

function Reviews() {
  return <p>Sharhlar: "Osh zo'r!" — Malika</p>;
}

export default function App() {
  const [tab, setTab] = useState("order");
  function showNote() {
    const input = document.querySelector("input");
    console.log("izohda:", JSON.stringify(input.value));
  }
  return (
    <div>
      <button onClick={() => setTab("order")}>Buyurtma</button>{" "}
      <button onClick={() => setTab("reviews")}>Sharhlar</button>{" "}
      <button onClick={showNote}>Izoh?</button>
      {tab === "order" && <OrderForm />}
      {tab === "reviews" && <Reviews />}
    </div>
  );
}

Konsolda:

text
izohda: ""

"Piyozsiz" yo'qoldi. «Sharhlar» bosilganda OrderForm daraxtdan chiqdi (unmount), qaytganda — yangi OrderForm, yangi state, bo'sh maydon.

2.2 Eski yechimlar va ularning narxi

Ilgari bu muammoni uch yo'l bilan hal qilishardi:

Yo'l Nima qiladi Narxi
state'ni ko'tarish (state'ni ko'tarish) izoh App da saqlanadi har tabning hamma state'ini yuqorida yig'ish; scroll, fokus baribir yo'qoladi
CSS bilan yashirish (hidden, display: none) komponent doim chizilgan, faqat ko'rinmaydi yashirin tabning effektlari ishlayveradi: taymerlar, obunalar, so'rovlar
localStorage ga saqlash qaytganda tiklanadi qo'shimcha kod, faqat oddiy qiymatlar uchun

Ikkinchi yo'l eng yaqin — lekin uning muammosi jiddiy. Yashirin «Sharhlar» tabi har 10 soniyada serverdan yangi sharh so'rasa, u ko'rinmasa ham so'rayveradi. O'nta yashirin tab — o'nta behuda so'rov oqimi. <Activity> — "CSS bilan yashirish, lekin effektlarni to'xtatib".

3. <Activity>

3.1 State saqlanadi

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

function OrderForm() {
  const [note, setNote] = useState("");
  return (
    <p>
      <label>
        Izoh{" "}
        <input
          value={note}
          onChange={(e) => setNote(e.target.value)}
        />
      </label>
    </p>
  );
}

function Reviews() {
  return <p>Sharhlar: "Osh zo'r!" — Malika</p>;
}

export default function App() {
  const [tab, setTab] = useState("order");
  function showNote() {
    const input = document.querySelector("input");
    console.log("izohda:", JSON.stringify(input.value));
  }
  return (
    <div>
      <button onClick={() => setTab("order")}>Buyurtma</button>{" "}
      <button onClick={() => setTab("reviews")}>Sharhlar</button>{" "}
      <button onClick={showNote}>Izoh?</button>
      <Activity mode={tab === "order" ? "visible" : "hidden"}>
        <OrderForm />
      </Activity>
      <Activity mode={tab === "reviews" ? "visible" : "hidden"}>
        <Reviews />
      </Activity>
    </div>
  );
}

Konsolda:

text
izohda: "Piyozsiz"

Ekranda:

text
Buyurtma Sharhlar Izoh?
Izoh

"Piyozsiz" joyida. «Sharhlar» ochiq paytda (ekran tekshirdi) OrderForm ko'rinmadi, lekin daraxtdan chiqmadi. «Ekranda» bo'limida sharhlar yo'q: yashirin Activity ichi display: none — sinov vositasi ham, foydalanuvchi ham uni ko'rmaydi.

mode faqat ikki qiymat oladi: "visible" (standart) va "hidden". Kodda o'zgargan narsa — {shart && …} o'rniga <Activity mode={shart ? "visible" : "hidden"}>.

3.2 Yashirinda nima bo'ladi

Shartli chizish (false) CSS hidden <Activity mode="hidden">
DOM yo'q bor bor, display: none
state yo'qoladi saqlanadi saqlanadi
effektlar cleanup, keyin yo'q ishlayveradi cleanup — to'xtatiladi
props o'zgarsa qayta chizish — odatdagidek fonda, eng past ustuvorlikda
qaytganda yangidan, effektlar yangidan darhol darhol, effektlar qayta ulanadi

Oxirgi ustun — <Activity> ning mohiyati: DOM va state — saqlanadi, effektlar — to'xtaydi.

4. Effektlar to'xtaydi

4.1 Konsolda

«Sharhlar» tabi yangi sharhlarni kuzatib turadi — real ilovada bu WebSocket yoki har 10 soniyada so'rov bo'lardi (Effekt). Effektni log bilan kuzatamiz:

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

function Reviews() {
  useEffect(() => {
    console.log("sharhlar kuzatuvi: ulandi");
    return () => console.log("sharhlar kuzatuvi: uzildi");
  }, []);
  return <p>Sharhlar: 5 ta</p>;
}

export default function App() {
  const [tab, setTab] = useState("menu");
  return (
    <div>
      <button onClick={() => setTab("menu")}>Menyu</button>{" "}
      <button onClick={() => setTab("reviews")}>Sharhlar</button>
      <Activity mode={tab === "menu" ? "visible" : "hidden"}>
        <p>Osh, lag'mon, manti</p>
      </Activity>
      <Activity mode={tab === "reviews" ? "visible" : "hidden"}>
        <Reviews />
      </Activity>
    </div>
  );
}

Konsolda:

text
sharhlar kuzatuvi: ulandi
sharhlar kuzatuvi: uzildi
sharhlar kuzatuvi: ulandi

Ochilishda «Sharhlar» yashirin — effekt ulanmadi (konsol bo'sh). Ochildi — ulandi. Yopildi — uzildi (cleanup). Yana ochildi — qayta ulandi. Yashirin paytda kuzatuv yo'q: so'rov ketmaydi, batareya sarflanmaydi.

E'tibor bering: bu xuddi StrictMode dagi "setup → cleanup → setup" sinovi. StrictMode effektlaringiz shunga tayyorligini oldindan tekshirgan edi. Cleanup'i to'g'ri yozilgan effekt <Activity> ichida ham to'g'ri ishlaydi. Cleanup'i yo'q effekt esa har ochilishda yangi ulanish qo'shadi — Effekt hayot sikli dagi oqish.

4.2 Nima to'xtamaydi

<Activity> faqat React effektlarini to'xtatadi. DOM'ning o'z xulqi davom etadi:

  • Yashirin <video> yoki <audio> o'ynashda davom etadi — display: none ovozni o'chirmaydi. Effekt cleanup'ida pause() chaqiring.
  • Effektdan tashqarida (modul darajasida) boshlangan setInterval to'xtamaydi — React u haqda bilmaydi.
  • State saqlanadi — bu ham xotira. Yuzta yashirin tab — yuzta komponent daraxti xotirada.
jsx
function VideoTab({ src }) {
  const ref = useRef(null);
  // Yashirilganda — cleanup: video to'xtaydi
  useLayoutEffect(() => {
    const video = ref.current;
    return () => video.pause();
  }, []);
  return <video ref={ref} src={src} controls />;
}

React hujjati bu yerda useLayoutEffect ni tavsiya qiladi: cleanup Activity yashirilishi bilan bir vaqtda, bo'yashdan oldin ishlaydi (useLayoutEffect).

Tekshirib ko'ring: Yashirin «Sharhlar» tabining props'i o'zgarsa (masalan, count 5 dan 6 ga), Reviews qayta chiziladimi?

Javob

Ha, lekin fonda, eng past ustuvorlikda — ko'rinib turgan qismning hamma ishi tugagach. Natija DOM'ga yoziladi (yashirin holda). Effektlar esa ishga tushmaydi. Tab ochilganda yangi count allaqachon chizilgan bo'ladi — qayta hisoblash kerak emas.

5. Oldindan chizish (prerender)

5.1 Yashirin boshlansa — fonda chiziladi

<Activity mode="hidden"> boshidanoq yashirin bo'lsa ham, React ichini chizadi — lekin faqat ko'rinadigan qism tayyor bo'lgach, eng past ustuvorlikda. Effektlar esa ishga tushmaydi:

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

function Reviews() {
  console.log("Reviews chizildi");
  useEffect(() => {
    console.log("Reviews effekti");
  }, []);
  return <p>Sharhlar: 5 ta</p>;
}

export default function App() {
  const [tab, setTab] = useState("menu");
  useEffect(() => {
    console.log("App commit bo'ldi");
  }, []);
  return (
    <div>
      <button onClick={() => setTab("reviews")}>Sharhlar</button>
      <Activity mode={tab === "reviews" ? "visible" : "hidden"}>
        <Reviews />
      </Activity>
    </div>
  );
}

Konsolda:

text
App commit bo'ldi
Reviews chizildi
Reviews chizildi
Reviews effekti

Tartibga qarang:

Qadam Nima bo'ldi
1 App chizildi va commit bo'ldi — tugma ekranda
2 keyin, fonda: Reviews chizildi (yashirin), effekti — yo'q
3 «Sharhlar» bosildi: Reviews ko'rinadigan qilib qayta chizildi
4 effekt endi ishga tushdi

Ikkinchi qadam — prerender. Foydalanuvchi tugmani ko'rgan paytda React bo'sh vaqtda keyingi tabni tayyorlab qo'ydi. Bosilganda DOM tayyor — faqat ko'rsatish qoladi.

Bu — Suspense bilan ham ishlaydi. Yashirin Activity ichidagi use(promise) yoki lazy komponent fonda yuklanishni boshlaydi. Tab ochilganda ma'lumot va kod allaqachon kelgan bo'lishi mumkin.

5.2 Prerender'ning narxi

Bepul tushlik yo'q. Fonda chizish — baribir ish: protsessor vaqti, xotira, tarmoq so'rovlari (yashirin lazy chunk'ni yuklaydi). Foydalanuvchi o'sha tabni hech ochmasa — hammasi behuda.

vazifalar kanonida aynan shu masala chiqdi. Statistika paneli — lazy chunk va og'ir hisob. Agar panel sahifa ochilishida <Activity mode="hidden"> bilan qurilsa, React uni fonda chizadi. Natijada chunk yuklanadi va 10 000 vazifa hisoblanadi — panelni hech kim ochmasa ham. Bu lazy darsidagi butun yutuqni yo'qqa chiqarardi.

Kanondagi yechim — Activity'ni birinchi ochilishdan keyin qurish:

jsx
const [ochilgan, setOchilgan] = useState(false);
// ...
{ochilgan && (
  <Activity mode={ochiq ? "visible" : "hidden"}>
    <BatafsilStatistika vazifalar={kechikkan} />
  </Activity>
)}

Birinchi ochilishgacha — hech narsa (na chunk, na hisob). Ochilgandan keyin — Activity: yopilsa yashirinadi va state saqlanadi.

Qachon ochilgan Ekranda Fonda
sahifa ochildi false tugma hech narsa — chunk yuklanmaydi
1-ochilish true panel —
yopildi true tugma panel DOM'da, effektlar to'xtagan
qayta ochildi true panel darhol, tanlov saqlangan —

Qoida: prerender — ehtimoli yuqori keyingi ekran uchun. Ehtimoli past va og'ir narsa uchun — avval birinchi ochilish, keyin saqlash.

6. Qaysi biri qachon

flowchart TD
  Q{"Yopilganda state saqlansinmi?"} -- "yo'q" --> C["Shartli chizish: {open && ...}"]
  Q -- "ha" --> E{"Ichida effekt bormi?"}
  E -- "yo'q, oddiy kontent" --> H["CSS hidden ham bo'ladi"]
  E -- "ha" --> A["Activity"]
  A --> P{"Oldindan chizish arzonmi?"}
  P -- "ha, ehtimoliy keyingi ekran" --> AH["boshidan hidden"]
  P -- "yo'q, og'ir yoki kamdan-kam" --> AO["1-ochilishdan keyin"]

Diagrammadan tashqari yana bir vosita bor — key. U teskari ishni qiladi: state'ni ataylab tashlaydi (State'ning saqlanishi va key). Masalan, boshqa foydalanuvchi profili ochilganda forma toza bo'lsin. Activity "saqlash", key "yangilash" uchun.

Tekshirib ko'ring: Router'dagi 20 ta sahifaning hammasini <Activity> bilan o'rab qo'yish yaxshi fikrmi?

Javob

Yo'q. Har yashirin sahifa — xotirada butun komponent daraxti va DOM. Boshidan yashirin bo'lsa — yana fonda chizish va yuklash. Bir nechta "orqaga qaytish ehtimoli yuqori" sahifa (masalan, ro'yxat → tafsilot → yana ro'yxat) uchun Activity foydali. Hammasi uchun — xotira va ish isrofi. Framework'lar (Next.js) buni o'zi hal qiladi.

7. Vazifalar qadami: statistika paneli — <Activity> (holat 11)

7.1 Saqlanadigan narsa

Activity kerakligini ko'rish uchun panelda saqlanadigan state bo'lishi kerak. Kanonda BatafsilStatistika ga «Teglar tartibi» tanlovi qo'shildi:

tsx
  // Komponentning o'z state'i: panel yopilib-ochilganda saqlanadimi —
  // 18/#11 (<Activity>) shuni ko'rsatadi
  const [tartib, setTartib] = useState<"soni" | "alifbo">("soni");
  const tanlovId = useId();
  const teglar =
    tartib === "soni"
      ? s.teglar
      : s.teglar.toSorted((a, b) => (a.teg < b.teg ? -1 : 1));

teglar — hosilaviy qiymat: state — faqat tanlov, tartiblangan ro'yxat har renderda hisoblanadi. toSorted — asl massivni o'zgartirmaydigan saralash (massiv metodlari). Tanlov — native <select> va <label> (useId bilan).

7.2 StatistikaPaneli.tsx

diff
+  // Activity birinchi ochilishdan KEYIN quriladi: yashirin (hidden)
+  // holatda boshlansa, React uni fonda baribir chizadi (oldindan
+  // render) — lazy chunk va hisob sahifa ochilishida ishlab ketardi
+  const [ochilgan, setOchilgan] = useState(false);
diff
           onClick={() =>
             boshla(() => {
               setOchiq((o) => !o);
+              setOchilgan(true);
             })
           }
diff
-          <div
-            id={panelId}
-            hidden={!ochiq}
-            aria-busy={eskirgan || undefined}
-          >
-            {ochiq && <BatafsilStatistika vazifalar={kechikkan} />}
+          <div id={panelId} aria-busy={eskirgan || undefined}>
+            {ochilgan && (
+              // hidden: ichi display: none, effektlari to'xtaydi,
+              // yangilanishlar — eng past ustuvorlikda; state joyida
+              <Activity mode={ochiq ? "visible" : "hidden"}>
+                <BatafsilStatistika vazifalar={kechikkan} />
+              </Activity>
+            )}
           </div>

Kanondan (diff, izohlar qayta bo'lingan). Ikki narsa o'zgardi:

  • hidden={!ochiq} atributi ketdi. Yashirishni endi Activity qiladi (display: none).
  • {ochiq && …} → {ochilgan && <Activity …>}. Birinchi ochilishgacha — hech narsa, keyin — Activity.

Yashirin panel props o'zgarishini ham oladi: katak bosilsa, statistika fonda, eng past ustuvorlikda qayta hisoblanadi. Panel ochilganda — tayyor.

7.3 CSP va display: none

vazifalar qat'iy CSP ostida ishlaydi: inline stil atributlari taqiqlangan bo'lishi mumkin (Frontend xavfsizligi). Activity display: none ni qanday qo'yadi? Haqiqiy Chrome'da tekshirildi: React uni element.style orqali (CSSOM) yozadi — HTML atributi emas. CSP buzilishi — 0.

7.4 Haqiqiy brauzerda

e2e-18 (Chrome 155, natija-18-11.txt):

text
✅ activity: boshida «ko'pi oldin»: "#bozor"
✅ activity: alifbo tanlandi: "#aka"
✅ activity: yopildi — DOM joyida, display: none (CSSOM, CSP'ga mos): [true,"none"]
✅ activity: qayta ochildi — tanlov saqlangan (alifbo), fallback yo'q: ["alifbo","#aka",0]
✅ activity: CSP buzilishi yo'q: []

Panel yopildi — DOM joyida, display: none. Qayta ochildi — tanlov "alifbo" bo'yicha qoldi, birinchi teg #aka, fallback bir marta ham ko'rinmadi.

7.5 Commit

bash
git switch -c feat/statistika-activity
git add -A
git commit

Commit (kanon): feat: statistika paneli <Activity> bilan — yopilganda holat saqlanadi. Tekshiruvlar: Vitest Tests 38 passed (38) (+1), node:test 163, lint, format, tip — toza. Brauzer — 159/159, e2e-18 — 34/34. Diff: 3 fayl, +87 −9.

Activity barqarorligi ham tekshirildi: React 19.3.0 da react paketidan oddiy eksport, @types/react 19.3.0 da ActivityProps turi bor. Eksperimental (unstable_) emas.

8. Ko'p uchraydigan xatolar

Belgi Sabab Davosi
tab almashganda yozilgan matn yo'qoladi {shart && …} — unmount <Activity mode={…}>
yashirin tab baribir so'rov yuboradi CSS hidden — effektlar ishlayveradi <Activity> — effektlar to'xtaydi
har ochilishda ulanishlar ko'payadi effektda cleanup yo'q cleanup; StrictMode buni oldindan ko'rsatadi
yashirin video ovoz chiqaradi display: none media'ni to'xtatmaydi layout effekt cleanup'ida pause()
sahifa ochilishida keraksiz chunk/hisob boshidan hidden — prerender birinchi ochilishdan keyin qurish
xotira o'sib boradi juda ko'p yashirin daraxt faqat qaytish ehtimoli yuqori qismlar

9. Mashqlar

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

1-mashq (oson): nima bo'ladi?

<Activity mode="hidden"> ichidagi komponent uchun ha yoki yo'q:

  • State saqlanadimi?
  • useEffect ichidagi obuna ishlab turadimi?
  • DOM'da elementlar bormi?
  • Boshidan hidden bo'lsa, komponent funksiyasi chaqiriladimi?
Yechim
  • ha — daraxtdan chiqmaydi.
  • yo'q — yashirilganda cleanup ishlaydi; ochilganda qayta ulanadi.
  • ha — display: none bilan.
  • ha — prerender: fonda, eng past ustuvorlikda chiziladi, lekin effektlarsiz.

2-mashq (o'rta): savat soni yo'qolmasin

Ikki tab: «Menyu» (ichida «+1» tugmasi va "Savatda: N") va «Manzil». Tab almashganda savat soni 0 ga tushyapti. <Activity> bilan tuzating — Cart komponentining kodiga tegmang. Ishora: «State saqlanadi» bo'limi.

jsx
import { useState } from "react";

function Cart() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>Savatda: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

export default function App() {
  const [tab, setTab] = useState("menu");
  return (
    <div>
      <button onClick={() => setTab("menu")}>Menyu</button>{" "}
      <button onClick={() => setTab("address")}>Manzil</button>
      {tab === "menu" && <Cart />}
      {tab === "address" && <p>Chilonzor, 9-kvartal</p>}
    </div>
  );
}

Ekranda:

text
Menyu Manzil
Savatda: 0
+1
Yechim
jsx
import { Activity, useState } from "react";

function Cart() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>Savatda: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

export default function App() {
  const [tab, setTab] = useState("menu");
  return (
    <div>
      <button onClick={() => setTab("menu")}>Menyu</button>{" "}
      <button onClick={() => setTab("address")}>Manzil</button>
      <Activity mode={tab === "menu" ? "visible" : "hidden"}>
        <Cart />
      </Activity>
      {tab === "address" && <p>Chilonzor, 9-kvartal</p>}
    </div>
  );
}

Ekranda:

text
Menyu Manzil
Savatda: 2
+1

«Manzil» tabida Cart yashirindi, lekin daraxtdan chiqmadi — count 2 saqlandi. Manzil esa oddiy shartli chizishda qoldi: unda state yo'q, saqlashning foydasi ham yo'q.

3-mashq (qiyin): taymer yashirinda to'xtasin

«Buyurtma holati» tabi har 100 ms da serverdan holatni "so'raydi" (setInterval). Hozir tab CSS hidden bilan yashiriladi — yashirin paytda ham so'rayveradi. <Activity> ga o'tkazing: yashirin paytda so'rov to'xtasin, qaytganda — davom etsin. Qaytganda konsolga yashirin paytdagi so'rovlar soni chiqsin — u 0 bo'lishi kerak.

Sinov: tab ochiq (250 ms) → yopiladi (400 ms) → ochiladi (250 ms). Ishora: «Effektlar to'xtaydi» bo'limi; interval cleanup'da clearInterval.

jsx
function OrderStatus() {
  useEffect(() => {
    const id = setInterval(() => console.log("so'rov"), 100);
    return () => clearInterval(id);
  }, []);
  return <p>Buyurtma: tayyorlanmoqda</p>;
}
// App: <div hidden={tab !== "status"}><OrderStatus /></div>
Yechim
jsx
import { Activity, useEffect, useState } from "react";

let requests = 0; // "serverga" ketgan so'rovlar
let stoppedAt = null; // to'xtagan paytdagi soni

function OrderStatus() {
  useEffect(() => {
    if (stoppedAt === null) {
      console.log("kuzatuv: boshlandi");
    } else {
      const extra = requests - stoppedAt;
      console.log(`kuzatuv: qaytdi, yashirinda ${extra} ta so'rov`);
    }
    const id = setInterval(() => requests++, 100);
    return () => {
      clearInterval(id);
      stoppedAt = requests;
      console.log("kuzatuv: to'xtadi");
    };
  }, []);
  return <p>Buyurtma: tayyorlanmoqda</p>;
}

export default function App() {
  const [tab, setTab] = useState("status");
  return (
    <div>
      <button onClick={() => setTab("status")}>Holat</button>{" "}
      <button onClick={() => setTab("menu")}>Menyu</button>
      <Activity mode={tab === "status" ? "visible" : "hidden"}>
        <OrderStatus />
      </Activity>
      {tab === "menu" && <p>Osh, lag'mon</p>}
    </div>
  );
}

Konsolda:

text
kuzatuv: boshlandi
kuzatuv: to'xtadi
kuzatuv: qaytdi, yashirinda 0 ta so'rov

Ekranda:

text
Holat Menyu
Buyurtma: tayyorlanmoqda

«Menyu» ochiq bo'lgan ~400 ms davomida bitta ham so'rov yo'q — effekt cleanup'i intervalni to'xtatdi. So'rovlar sonini to'g'ridan-to'g'ri chiqarmadik: u vaqtga bog'liq. Farq esa — aniq 0. «Holat» ga qaytganda effekt qayta ulandi. OrderStatus kodi o'zgarmadi: to'g'ri yozilgan cleanup Activity bilan o'z-o'zidan ishladi. CSS hidden bilan esa 400 ms da yana 4 ta "so'rov" bo'lardi.

4-mashq: Vazifalar qadami

feat/statistika-activity branch'ida BatafsilStatistika ga «Teglar tartibi» tanlovini, StatistikaPaneli ga ochilgan va <Activity> ni qo'shing. Vitest: tanlov alifboga o'tkazilib, panel yopilib-ochilganda saqlanadi. Commit qiling va PR oching.

Yechim

Tekshiruv ro'yxati:

  • npm run preview → DevTools → Network: sahifa ochilganda statistika chunk'i yuklanmaydi (Activity hali yo'q). Bu ochilgan siz qilinsa, chunk darhol yuklanardi — tekshirib ko'ring va qaytaring.
  • Panelni oching, «Alifbo bo'yicha» ni tanlang, yoping, oching — tanlov joyida. Elements'da yopiq panel — style="display: none !important;".
  • DevTools → Console: CSP ogohlantirishi yo'q.
  • npm test — Vitest 38. Commit — feat: statistika paneli <Activity> bilan — yopilganda holat saqlanadi.

10. Real ishda

  • Tablar, yon panellar, "orqaga" navigatsiya — Activity'ning asosiy uyi. Ro'yxat → tafsilot → orqaga: ro'yxatning scroll va filtrlari joyida.
  • Framework'lar — Next.js va React Router ichki navigatsiyada Activity'dan foydalanib, oldingi sahifani saqlashi va keyingisini oldindan chizishi mumkin (Next.js performance).
  • Mobil tajriba — native ilovalardagi "tab bar" xulqi (har tab o'z holatida) — web'da endi oddiy React bilan.
  • Intervyu savollari: "<Activity> va shartli chizish farqi?", "yashirin Activity'da effektlar bilan nima bo'ladi?", "prerender nima va qachon zararli?".

Xulosa

  • <Activity mode="hidden"> — DOM va state saqlanadi, effektlar to'xtaydi (cleanup), display: none.
  • visible ga qaytganda — darhol, effektlar qayta ulanadi; to'g'ri cleanup — shart.
  • Boshidan hidden — fonda, past ustuvorlikda prerender (effektlarsiz); Suspense/lazy yuklanishni ham boshlaydi.
  • Prerender — ehtimoliy keyingi ekran uchun; og'ir va kamdan-kam narsa — birinchi ochilishdan keyin.
  • Media (<video>) va effektdan tashqaridagi taymerlar o'zi to'xtamaydi.
  • vazifalar: statistika paneli — ochilgan && <Activity>; tanlov saqlanadi, chunk sahifa ochilishida yuklanmaydi.

Keyingi dars: Hujjat metadata va resurs API'lari — <title>, <meta>, <link> ni komponent ichida yozish va resurslarni oldindan yuklash.

Manbalar

  • React: <Activity> — react.dev/reference/react/Activity (2026-10 holati, React 19.3)
  • React blog: "React 19.2" (2025-10-01) — <Activity> — react.dev/blog/2025/10/01/react-19-2
  • React: "Preserving and Resetting State" — react.dev/learn/preserving-and-resetting-state
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
React Activity: yashirin UI holatini saqlash, effektlarni to'xtatish va oldindan chizish — IlmHamroh