WisarWisar
Dasturlash kitobi/11-QISM — React43 daqiqa

11.13-bob: React pattern'lar — HOC, render props, compound components

11-QISM — Frontend: React · 13-mavzu


1. Kirish va motivatsiya

11.7-bobda custom hooklar bilan mantiqni qayta ishlatishni o'rgandik — bu zamonaviy React'ning asosiy usuli. Lekin React 7+ yil tarixga ega va hooklardan oldin ham mantiq va UI'ni qayta ishlatish kerak edi. O'sha davrda ikkita klassik naqsh ishlatilardi: HOC (Higher-Order Component) va render props. Bu naqshlarni bilish ikki sababga ko'ra muhim: (1) ko'p mavjud kod va kutubxona (eski va yangi) ularni ishlatadi — siz ularni o'qiy va tushuna olishingiz kerak; (2) ba'zi holatlarda (ayniqsa compound components) ular hali ham eng yaxshi yechim. Bundan tashqari, bu naqshlarni tushunish — React'ning chuqur falsafasini (kompozitsiya, mas'uliyat ajratish) anglashga yordam beradi.

Bu bobda uchta pattern'ni ko'ramiz, har biri mantiq yoki UI'ni qayta ishlatishning turli usuli. HOC — komponentni o'rovchi funksiya (withAuth(Component) — komponentga qo'shimcha imkoniyat "qo'shadi"). Render props — komponent o'z mantig'ini funksiya prop orqali ulashadi (<Mouse>{pos => ...}</Mouse>). Va eng muhimi, hali ham keng ishlatiladigan — compound components — bir-biriga bog'liq komponentlar oilasi (<Tabs>, <Tabs.Tab>, <Tabs.Panel> — birgalikda ishlaydi, holatni Context orqali ulashadi). Bu naqshlarni custom hooklar 11.7-bob bilan solishtiramiz — qachon qaysi biri afzal — va UI kutubxonalar (Radix, MUI) qanday qurilganini tushunamiz.

Bu bob: nega pattern'lar (mantiq/UI qayta ishlatish — custom hook bilan taqqos), HOC (nima, qanday yoziladi/ishlatiladi, muammolari — wrapper hell, props to'qnashuvi — nega hook afzal), render props (nima, qanday, children as function, hooklar bilan taqqos), compound components (nima — Tab/Accordion/Select, Context bilan, control props/state reducer — ilg'or, prop getters), va qachon qaysi pattern (hook default, compound UI uchun). Bu naqshlarning har birini to'liq va amaliy holatda ochamiz.

O'xshatish: Bu pattern'lar — bir narsani o'rashning uch xil usuli (sovg'a qadoqlash). HOC — bu tashqi quti: sovg'ani (komponentni) qutiga solasiz, qutiga qo'shimcha narsalar (yorliq, lenta — qo'shimcha props) qo'shasiz. Lekin ko'p quti ichma-ich bo'lsa — ochish qiyin (wrapper hell). Render props — bu "o'zingiz qadoqla" xizmati: do'kon sizga materiallar (mantiq) beradi, qanday qadoqlashni (UI) siz funksiya orqali aytasiz — moslashuvchan, lekin har safar yozasiz. Custom hook 11.7-bob — bu zamonaviy yetkazib berish: materiallar to'g'ridan keladi (funksiya chaqiruvi — useMouse()), ortiqcha quti yo'q (eng toza). Compound components — bu mebel to'plami: stol (<Tabs>) va stullar (<Tab>) alohida keladi, lekin birga ishlashga mo'ljallangan (bir uslubda, bir-birini "biladi") — foydalanuvchi ularni erkin joylashtiradi.

Nega muhim?

  • Mavjud kodni o'qiy olish — ko'p kutubxona/eski kod HOC/render props ishlatadi (tushunmasangiz, ishlay olmaysiz).
  • Compound components — Tab, Accordion, Modal, Select kabi murakkab UI'ning eng yaxshi naqshi (hali keng).
  • Kutubxona dizayni — Radix, MUI, Headless UI shu naqshlarga qurilgan (qanday ishlashini tushunasiz).
  • Chuqur React — kompozitsiya, mas'uliyat ajratish, moslashuvchan API — senior dizayn tafakkuri.

2. Nazariya — chuqur tushuntirish

2.1. Nega pattern'lar — mantiq/UI qayta ishlatish

text
  MUAMMO: bir nechta komponent BIR XIL mantiq yoki UI tuzilishini ishlatadi
   uni qanday QAYTA ISHLATISH (DRY — 9.1)?

  3 YONDASHUV (tarixiy tartibda):
  1. HOC (eski) — komponentni o'rovchi funksiya (withX(Component))
  2. RENDER PROPS (eski) — funksiya prop orqali mantiq ulashish
  3. CUSTOM HOOK (zamonaviy — 11.7) — mantiqni funksiya sifatida (useX())

  MANTIQ vs UI qayta ishlatish:
  - MANTIQ (state, effect, data)  custom hook 11.7-bob afzal (zamonaviy, toza)
  - UI TUZILISHI / KOMPOZITSIYA  compound components 2.9-bob yoki render props

  ┌────────────────────────────────────────────────────────────┐
  │ Mantiq ulashish: HOC/render props  ENDI custom hook 11.7-bob  │
  │ UI tuzilishi ulashish: compound components (hook qila olmaydi) │
  └────────────────────────────────────────────────────────────┘

   Hooklar HOC/render props'ning KO'PINI almashtirdi (mantiq uchun)
   LEKIN compound components — hali ham UI naqshi uchun eng yaxshi (hook emas)

Nega pattern'lar — bir nechta komponent bir xil mantiq yoki UI tuzilishini ishlatganda, uni qanday qayta ishlatish (DRY — 9.1) muammosini hal qiladi. Tarixiy tartibda uch yondashuv: HOC (eski — komponentni o'rovchi funksiya, withX(Component)), render props (eski — funksiya prop orqali mantiq ulashish), custom hook (zamonaviy — 11.7 — mantiqni funksiya sifatida, useX()). Muhim ajratish — nimani qayta ishlatish: (1) mantiq (state, effect, data fetching, obuna) custom hook afzal (zamonaviy, toza, "wrapper hell"siz — 11.7: 2.1); (2) UI tuzilishi/kompozitsiya (bir-biriga bog'liq komponentlar oilasi) compound components 2.9-bob yoki render props — bularni hook qila olmaydi. Ikki muhim xulosa: (1) hooklar HOC/render props'ning ko'pini almashtirdi — mantiq ulashish uchun endi custom hook ishlatiladi (HOC/render props eski kodda qoladi); (2) lekin compound components — UI komponentlari o'rtasida holat va kontekstni ulashish naqshi sifatida hali ham eng yaxshi (hook bu vazifani bajara olmaydi). Demak pattern'lar eskirmagan — har biri o'z o'rnida. Bu bob ularni qachon va qanday ishlatishni o'rgatadi.

2.1b. Komponent kompozitsiya — children, slot, komponent prop

text
  KOMPOZITSIYA — komponentni "ichiga qo'yish" (React'ning eng tabiiy qayta ishlatish usuli):

  1. children — eng oddiy: komponent ichidagi hamma narsa `props.children`:
  function Card({ children }) { return <div className="card">{children}</div>; }
  <Card><h2>Sarlavha</h2><p>Matn</p></Card>   // children = <h2/> + <p/>

  2. SLOT pattern — bir nechta "teshik" (nomlangan children):
  function Layout({ header, sidebar, children }) {
    return (<div><header>{header}</header><aside>{sidebar}</aside><main>{children}</main></div>);
  }
  <Layout header={<Nav/>} sidebar={<Menu/>}><Content/></Layout>   // JSX prop = slot

  3. KOMPONENT PROP — komponentni prop sifatida uzatish (turini boshqarish):
  function List({ items, ItemComponent }) {
    return items.map(x => <ItemComponent key={x.id} item={x} />);   // qaysi komponent — prop
  }
  <List items={users} ItemComponent={UserCard} />   // <List items={products} ItemComponent={ProductCard}/>

   Kompozitsiya — "prop drilling"/HOC o'rniga ko'p muammoni hal qiladi (JSX'ni prop qil)
   children/slot — Context'siz, HOC'siz UI qayta ishlatishning eng toza usuli

Komponent kompozitsiya — HOC/render props'dan oldin o'ylab ko'rish kerak bo'lgan eng tabiiy usul. React'da qayta ishlatishning asosi — komponentni boshqa komponent ichiga qo'yish (kompozitsiya), meros (inheritance) emas. Uch shakl: (1) children — eng oddiy: function Card({ children }) { return <div className="card">{children}</div> }<Card> ichidagi hamma narsa props.children bo'lib keladi (Card uni qayerga qo'yishni hal qiladi). Bu — "o'rash"ni HOC'siz beradi. (2) slot pattern — bir nechta "teshik": komponent bir nechta JSX'ni alohida prop sifatida oladi (<Layout header={<Nav/>} sidebar={<Menu/>}>...</Layout>) — har bir prop bir "slot"ga joylashadi (Vue'dagi slot yoki HTML <slot>ga o'xshash g'oya). (3) komponent prop — komponentning o'zini prop sifatida uzatish: <List items={users} ItemComponent={UserCard} />List umumiy mantiqni (ro'yxatlash) bajaradi, lekin har bir elementni qaysi komponent ko'rsatishini chaqiruvchi hal qiladi. Ikki muhim nuqta: (1) kompozitsiya ko'p holatlarda HOC yoki prop drilling'ni umuman keraksiz qiladi — masalan "layout"ni qayta ishlatish uchun HOC yozish shart emas, children/slot yetadi; (2) bu — React'ning eng toza, eng arzon (Context/wrapper'siz) usuli, shuning uchun birinchi navbatda shuni o'ylang, keyin murakkabroq naqshlarga (compound, HOC, render props) o'ting. React rasmiy hujjati ham buni ta'kidlaydi: "kompozitsiyani afzal ko'ring".

2.2. HOC nima — komponentni o'rovchi funksiya

text
  HOC (Higher-Order Component) — komponentni OLIB, yangi (kuchaytirilgan) komponent qaytaruvchi funksiya:

  const EnhancedComponent = withSomething(OriginalComponent);
  //                        └─ HOC: komponent kiradi, komponent chiqadi (+ qo'shimcha imkoniyat)

  TUZILISHI:
  function withLoading(Component) {            // HOC — komponent oladi
    return function WithLoading({ isLoading, ...props }) {   // yangi komponent qaytaradi
      if (isLoading) return <Spinner />;       // qo'shimcha mantiq (yuklanish)
      return <Component {...props} />;         // asl komponent (props uzatiladi)
    };
  }
  const UserListWithLoading = withLoading(UserList);   // kuchaytirilgan versiya

  ┌────────────────────────────────────────────────────────────┐
  │ HOC: f(Component)  yangi Component (qo'shimcha imkoniyat)   │
  │ (funksiya — komponent kiradi, komponent chiqadi)            │
  └────────────────────────────────────────────────────────────┘

   "Higher-order" — funksiyani/komponentni OLADIGAN funksiya (2.15 HOF — JS)
   HOC komponentni O'RAB, unga props/mantiq "qo'shadi" (loading, auth, theme)

HOC (Higher-Order Component) — komponentni olib, yangi (kuchaytirilgan) komponent qaytaruvchi funksiya. Nom "higher-order"dan keladi (2.15 — funksional dasturlashdagi higher-order function — funksiyani oluvchi/qaytaruvchi funksiya). HOC: const Enhanced = withSomething(Original)withSomething HOC, u Original komponentni olib, qo'shimcha imkoniyatli yangi komponent qaytaradi. Tuzilishi: function withLoading(Component) { return function(props) { if (props.isLoading) return <Spinner/>; return <Component {...props} /> } }withLoading HOC, u har qanday komponentga "yuklanish" mantig'ini qo'shadi (isLoading bo'lsa spinner, aks holda asl komponent). Ishlatish: const UserListWithLoading = withLoading(UserList). Ikki nuqta: (1) HOC — funksiya (komponent kiradi, komponent chiqadi), JSX komponenti emas; (2) u komponentni o'rab, unga umumiy mantiq/props "qo'shadi" — loading, auth, theme, ma'lumot. Konvensiya — HOC nomi with bilan boshlanadi (withAuth, withTheme, withRouter — eski React Router). HOC — hooklardan oldingi davrning asosiy mantiq-ulashish naqshi edi.

2.3. HOC yozish va ishlatish

text
  HOC NAQSHLARI:

  1. PROPS QO'SHISH (komponentga ma'lumot/imkoniyat beradi):
  function withUser(Component) {
    return function (props) {
      const user = useAuth().user;             // mantiqni bajaradi
      return <Component {...props} user={user} />;   // user prop'ini QO'SHADI
    };
  }
  const ProfileWithUser = withUser(Profile);   // Profile endi "user" prop oladi

  2. SHARTLI RENDER (yuklanish, ruxsat):
  function withAuth(Component) {
    return function (props) {
      const { user } = useAuth();
      if (!user) return <Navigate to="/login" />;   // himoya 11.9-bob
      return <Component {...props} />;
    };
  }

  3. KOMPOZITSIYA (bir nechta HOC):
  const Enhanced = withAuth(withLoading(withTheme(MyComponent)));   // ichma-ich (2.4 muammosi)

   HOC props'ni {...props} bilan UZATADI (asl komponent o'z props'ini olsin)
   HOC ichida hook ishlatsa bo'ladi (zamonaviy HOC) — lekin ko'pincha custom hook afzal (2.4)

HOC yozish va ishlatish — bir nechta naqsh. (1) Props qo'shish — komponentga ma'lumot/imkoniyat berish: withUser(Component) — asl komponentga user prop'ini qo'shadi (<Component {...props} user={user} /> — mavjud props'ni saqlab, yangisini qo'shadi). (2) Shartli render — yuklanish, ruxsat tekshiruvi: withAuth(Component) — foydalanuvchi yo'q bo'lsa login'ga yo'naltiradi (himoya — 11.9), aks holda komponentni ko'rsatadi. (3) Kompozitsiya — bir nechta HOC'ni birga ishlatish: withAuth(withLoading(withTheme(MyComponent))) — har biri o'z imkoniyatini qo'shadi (lekin ichma-ich — 2.4 muammosini keltiradi). Ikki muhim qoida: (1) HOC props'ni {...props} bilan uzatadi — asl komponent o'z props'ini yo'qotmasin (HOC faqat qo'shimcha qo'shadi, mavjudni bloklamaydi); (2) zamonaviy HOC ichida hook ishlatsa bo'ladi, lekin ko'p holda custom hook 11.7-bob HOC'dan ancha toza — shuning uchun yangi kodda mantiq uchun HOC kam yoziladi 2.4-bob. HOC'ni asosan o'qiy olish uchun bilib qo'yish kerak (eski kod, kutubxonalar).

2.3b. HOC — displayName, ref forwarding, props forwarding

text
  YAXSHI HOC UCHUN UCH DETAL:

  1. displayName — DevTools'da tushunarli nom (aks holda "Anonymous"/"WithLoading"):
  function withLoading(Component) {
    function WithLoading({ isLoading, ...props }) { ... }
    const name = Component.displayName || Component.name || "Component";
    WithLoading.displayName = `withLoading(${name})`;   // DevTools: withLoading(UserList)
    return WithLoading;
  }

  2. PROPS FORWARDING — {...props} bilan asl props'ni uzatish (HOC yutmasin — 2.3):
  return <Component {...props} extra={...} />;   // mavjud props saqlanadi

  3. REF FORWARDING — HOC ref'ni "yutadi" (wrapper komponent ref'ni ushlaydi):
  const WithLoading = forwardRef(function ({ isLoading, ...props }, ref) {
    if (isLoading) return <Spinner />;
    return <Component ref={ref} {...props} />;   // ref asl komponentga o'tsin
  });
  //  forwardRef'siz: <Enhanced ref={r}/>  wrapper'ga tegadi (asl DOM/komponentga emas)

   displayName — debug uchun majburiy (aks holda DevTools'da noaniq daraxt)
   ref forwarding — HOC ref'ni asl komponentga o'tkazishi kerak (aks holda ref ishlamaydi)

HOC — displayName, ref forwarding, props forwarding — sifatli HOC uchun uch detal. (1) displayName — HOC ichki komponentiga tushunarli nom berish. HOC yangi komponent yaratganda, React DevTools'da u anonim yoki noaniq (WithLoading) ko'rinadi — daraxtni o'qish qiyin. Yechim: WithLoading.displayName = \withLoading(${Component.displayName || Component.name})`— DevTools'dawithLoading(UserList)ko'rinadi (qaysi HOC qaysi komponentni o'ragani aniq). (2) **props forwarding** — HOC asl props'ni{...props}bilan uzatishi shart (2.3 — aks holda asl komponent o'z props'ini yo'qotadi). (3) **ref forwarding** — bu eng ko'p unutiladigan detal: HOC komponentni o'raganda,bilan berilganref**wrapper**'ga tegadi (asl komponentga yoki uning DOM'iga emas) — chunkirefoddiy prop emas, uni React alohida ushlaydi. Yechim: HOC'niforwardRefbilan o'rab,ref'ni asl komponentga qo'lda uzatish (<Component ref={ref} {...props} />). Ikki xulosa: (1) displayName— debug uchun deyarli majburiy (aks holda ko'p qatlamli daraxt tushunarsiz); (2)forwardRef— agar HOC bilan o'ralgan komponentga tashqaridanref` berilishi kutilsa, majburiy. Bu detallar HOC'ni to'g'ri yozishni murakkablashtiradi — yana bir sabab nega mantiq uchun custom hook 11.7-bob afzal: hook'da bu muammolarning hech biri yo'q (ref, props, displayName — hammasi tabiiy komponentniki bo'lib qoladi).

2.4. HOC muammolari — nega hook afzal

text
  HOC MUAMMOLARI (nega hooklar uni almashtirdi):

  1. WRAPPER HELL — ko'p HOC ichma-ich (debug/o'qish qiyin):
  withAuth(withLoading(withTheme(withRouter(Component))))   // 4 qatlam — chalkash
  // React DevTools'da: WithAuth > WithLoading > WithTheme > WithRouter > Component (shovqin)

  2. PROPS TO'QNASHUVI (props collision) — ikki HOC bir xil prop nomini bersa:
  withUserA(withUserB(C))   // ikkalasi "user" prop bersa — biri ikkinchisini bosadi (jim bug)

  3. QAYERDAN KELDI noaniq — prop qaysi HOC'dan keldi? (manba ko'rinmaydi)

  4. STATIK TURLAP (TypeScript) — HOC props turini "yo'qotadi" (murakkab generics)

  CUSTOM HOOK YECHIMI 11.7-bob — barcha muammoni hal qiladi:
  function Component() {
    const { user } = useAuth();          // QAYERDAN — aniq (chaqiruv ko'rinadi)
    const theme = useTheme();            // to'qnashuv yo'q (alohida o'zgaruvchi)
    // wrapper yo'q, manba aniq, tur saqlanadi
  }

   Hook — mantiqni "wrapper"siz ulashadi (manba aniq, to'qnashuv yo'q — 11.7: 2.1)
   Mantiq qayta ishlatish uchun: HOC EMAS  custom hook (zamonaviy standart)

HOC muammolari — nega hooklar HOC'ni (mantiq ulashish uchun) almashtirdi. To'rt muammo: (1) wrapper hell — ko'p HOC ichma-ich joylansa (withAuth(withLoading(withTheme(C)))), kod chalkash bo'ladi va React DevTools'da ko'p keraksiz qatlam ko'rinadi (debug/o'qish qiyin); (2) props to'qnashuvi (collision) — ikki HOC bir xil prop nomini (user) bersa, biri ikkinchisini jim bosib ketadi (topish qiyin bug); (3) manba noaniq — komponent prop'i qaysi HOC'dan kelganini ko'rish qiyin (chaqiruv ko'rinmaydi); (4) TypeScript turlari — HOC props turlarini to'g'ri saqlash murakkab (generics bilan kurashish). Custom hook 11.7-bob bularning hammasini hal qiladi: const { user } = useAuth() — manba aniq (chaqiruv ko'rinadi), to'qnashuv yo'q (alohida o'zgaruvchi), wrapper yo'q, tur saqlanadi. Ikki xulosa: (1) hook mantiqni "wrapper"siz, manba aniq, to'qnashuvsiz ulashadi (11.7: 2.1); (2) shuning uchun mantiq qayta ishlatish uchun zamonaviy standart — HOC emas, custom hook. HOC hali ham ba'zan ishlatiladi (masalan komponentni butunlay o'rash kerak bo'lganda — error boundary HOC, analytics tracking), lekin kam.

2.5. Render props nima

text
  RENDER PROPS — komponent o'z mantig'ini FUNKSIYA prop orqali ulashadi (UI'ni chaqiruvchi hal qiladi):

  <DataProvider render={(data) => <h1>{data.name}</h1>} />
  //            └─ "render" prop — funksiya (mantiq  UI; komponent mantiqni, chaqiruvchi UI'ni beradi)

  TUZILISHI:
  function MouseTracker({ render }) {
    const [pos, setPos] = useState({ x: 0, y: 0 });
    useEffect(() => {
      const onMove = (e) => setPos({ x: e.clientX, y: e.clientY });
      window.addEventListener("mousemove", onMove);
      return () => window.removeEventListener("mousemove", onMove);
    }, []);
    return render(pos);              //  mantiq (pos) ni funksiyaga beradi  UI chiqadi
  }

  // Ishlatish — UI'ni O'ZIM beraman (mantiq MouseTracker'da):
  <MouseTracker render={(pos) => <p>Sichqoncha: {pos.x}, {pos.y}</p>} />

  ┌────────────────────────────────────────────────────────────┐
  │ Render props: komponent MANTIQ beradi (pos); chaqiruvchi UI │
  │ (funksiya prop orqali — mantiq va ko'rinish ajratiladi)     │
  └────────────────────────────────────────────────────────────┘

   Render props — mantiqni komponent, UI'ni CHAQIRUVCHI beradi (moslashuvchan)
   "render" — shunchaki konvensiya (istalgan funksiya prop bo'ladi — 2.7 children)

Render props — komponent o'z mantig'ini funksiya prop orqali ulashadi (mantiqni komponent beradi, UI'ni chaqiruvchi hal qiladi). <DataProvider render={(data) => <h1>{data.name}</h1>} />render prop — funksiya (mantiq natijasini olib, JSX qaytaradi). Tuzilishi: MouseTracker sichqoncha holatini (pos) kuzatadi (state + effect), lekin uni qanday ko'rsatishni o'zi hal qilmaydi — return render(pos) bilan mantiqni (pos) funksiyaga beradi, funksiya esa UI qaytaradi. Ishlatish: <MouseTracker render={(pos) => <p>{pos.x}, {pos.y}</p>} /> — chaqiruvchi UI'ni (qanday ko'rsatish) o'zi beradi, mantiq (sichqoncha kuzatish) MouseTracker'da qoladi. Bu — mantiq va ko'rinishni ajratishning eski usuli (custom hook'dan oldin). Ikki nuqta: (1) render props moslashuvchan — bir xil mantiq (sichqoncha kuzatish) turli UI bilan ishlatiladi (chaqiruvchi UI'ni beradi); (2) render — shunchaki konvensiya (nom), istalgan funksiya prop ishlaydi — ko'pincha children funksiya sifatida ishlatiladi 2.7-bob. Render props — HOC'ning muqobili edi (wrapper hell'siz, lekin JSX'da ichma-ich — 2.8).

2.6. Render props yozish va children as function

text
  CHILDREN AS FUNCTION — render props'ning eng keng shakli (children — funksiya):

  function Toggle({ children }) {
    const [on, setOn] = useState(false);
    const toggle = () => setOn(o => !o);
    return children({ on, toggle });        //  children — FUNKSIYA (mantiqni beradi)
  }

  // Ishlatish — children funksiya (mantiq  UI):
  <Toggle>
    {({ on, toggle }) => (                   // children funksiyasi mantiqni oladi
      <button onClick={toggle}>{on ? "Yoqilgan" : "O'chiq"}</button>
    )}
  </Toggle>

  RENDER PROP vs CHILDREN FUNCTION (bir xil g'oya, sintaksis farqi):
  <X render={(d) => <UI/>} />          // render prop
  <X>{(d) => <UI/>}</X>                // children as function (tabiiyroq JSX)

  ┌────────────────────────────────────────────────────────────┐
  │ children as function: <Comp>{(data) => <UI/>}</Comp>        │
  │ (mantiq Comp'da, UI children funksiyasida — render prop turi)│
  └────────────────────────────────────────────────────────────┘

   children funksiya — render props'ning tabiiy JSX shakli (keng ishlatilgan)
   Ikkalasi bir xil g'oya: mantiq komponentda, UI funksiyada (chaqiruvchi beradi)

Render props yozish va children as function — render props'ning amaliy shakli. Children as function — render props'ning eng keng tarqalgan ko'rinishi: render prop o'rniga children funksiya bo'ladi. function Toggle({ children }) { ...; return children({ on, toggle }) }Toggle mantiqni (on, toggle) children funksiyasiga beradi. Ishlatish — children funksiya bo'ladi: <Toggle>{({ on, toggle }) => <button onClick={toggle}>{on ? "Yoqilgan" : "O'chiq"}</button>}</Toggle> — mantiq Toggle'da, UI children funksiyasida (chaqiruvchi beradi). Bu — render prop bilan bir xil g'oya, faqat sintaksis farqi: <X render={(d) => <UI/>} /> (render prop) vs <X>{(d) => <UI/>}</X> (children function — tabiiyroq JSX, ko'proq ishlatilgan). Ikki nuqta: (1) children as function — render props'ning tabiiy JSX shakli (komponent ichida UI joylashtirilgandek ko'rinadi, lekin funksiya orqali mantiq oladi); (2) ikkalasi ham bir xil tamoyil — mantiq komponentda, UI funksiyada (chaqiruvchi beradi — moslashuvchan). Bu naqsh eski kutubxonalarda (React Router v5 <Route render>, Formik, Downshift) juda keng edi, hozir ham ba'zan uchraydi.

2.7. Render props vs hooks

text
  BIR XIL MANTIQ — render props (eski) vs custom hook (zamonaviy):

  RENDER PROPS (ichma-ich, "pyramid of doom" ko'p mantiqda):
  <Mouse>
    {(pos) => (
      <Theme>
        {(theme) => (
          <Auth>
            {(user) => <div>...</div>}      // 3 qatlam ichma-ich (chalkash)
          </Auth>
        )}
      </Theme>
    )}
  </Mouse>

  CUSTOM HOOK (yassi, toza — 11.7):
  function Component() {
    const pos = useMouse();                // yassi — ichma-ich yo'q
    const theme = useTheme();
    const user = useAuth();
    return <div>...</div>;
  }

  ┌────────────────────────────────────────────────────────────┐
  │ Render props: JSX'da ichma-ich (ko'p mantiqda piramida)       │
  │ Custom hook: yassi, o'qish oson (mantiq uchun AFZAL — 11.7)  │
  └────────────────────────────────────────────────────────────┘

   MANTIQ ulashish uchun — custom hook (render props'ning piramida muammosini yo'qotadi)
   Render props HALI foydali: UI'ga bog'liq mantiq (masalan o'lcham/joylashuv beruvchi)

Render props vs hooks — qaysi biri qachon. Render props muammosi — ko'p mantiq ulashilganda JSX'da ichma-ich joylashish ("pyramid of doom"): <Mouse>{pos => <Theme>{theme => <Auth>{user => ...}</Auth>}</Theme>}</Mouse> — uch mantiq uch qatlam ichma-ich (chalkash, o'qish qiyin). Custom hook 11.7-bob buni hal qiladi — yassi: const pos = useMouse(); const theme = useTheme(); const user = useAuth() (ichma-ich yo'q, har biri alohida qator, o'qish oson). Demak mantiq ulashish uchun — custom hook afzal (render props'ning piramida muammosini yo'qotadi, xuddi HOC'ning wrapper hell'ini yo'qotgandek — 2.4). Ikki muhim nuqta: (1) mantiq ulashish uchun zamonaviy yo'l — custom hook (render props eski kodda qoladi); (2) lekin render props hali ham foydali bo'lgan holatlar bor — ayniqsa UI'ga bog'liq mantiq beradigan komponentlar (masalan o'lcham/joylashuv hisoblab beruvchi — <Measure>{({width}) => ...}</Measure>, yoki virtualization kutubxonalari — react-virtualized), va compound components 2.9-bob — bularda render props yoki bola-funksiya hali tabiiy. Demak render props o'lmagan, lekin oddiy mantiq uchun hook afzal.

2.8. Compound components nima

text
  COMPOUND COMPONENTS — bir-biriga BOG'LIQ komponentlar OILASI (birga ishlaydi):

  Misol — Tabs (yorliqlar):
  <Tabs defaultValue="profil">
    <Tabs.List>
      <Tabs.Tab value="profil">Profil</Tabs.Tab>       bola
      <Tabs.Tab value="sozlama">Sozlamalar</Tabs.Tab>
    </Tabs.List>
    <Tabs.Panel value="profil">Profil kontenti</Tabs.Panel>
    <Tabs.Panel value="sozlama">Sozlamalar kontenti</Tabs.Panel>
  </Tabs>

  XUSUSIYATLARI:
  - <Tabs> — "ota" (umumiy holat: qaysi tab faol — Context bilan ulashadi — 2.10)
  - <Tabs.Tab>, <Tabs.Panel> — "bolalar" (holatni Context'dan oladi)
  - Foydalanuvchi ularni ERKIN joylashtiradi (tartib, qo'shimcha element — moslashuvchan)

  ┌────────────────────────────────────────────────────────────┐
  │ Compound: bog'liq komponentlar oilasi (Tabs/Tab/Panel)      │
  │ holatni Context orqali yashirin ulashadi (foydalanuvchi bilmaydi)│
  └────────────────────────────────────────────────────────────┘

   Compound — <select>/<option> kabi (HTML'ning tabiiy naqshi — birga ishlaydi)
   Tab, Accordion, Menu, Select, Modal — compound components uchun ideal

Compound components — bir-biriga bog'liq komponentlar oilasi, ular birgalikda ishlashga mo'ljallangan. Misol — Tabs (yorliqlar): <Tabs> (ota), <Tabs.List>, <Tabs.Tab>, <Tabs.Panel> (bolalar). Bu HTML'ning tabiiy naqshiga o'xshaydi — <select> va <option> (ular birga ishlaydi, alohida ma'nosiz). Xususiyatlari: (1) <Tabs> — "ota", umumiy holatni boshqaradi (qaysi tab faol) va uni Context orqali bolalarga ulashadi 2.10-bob; (2) <Tabs.Tab>/<Tabs.Panel> — "bolalar", holatni Context'dan oladi (<Tabs> ichida bo'lishi shart); (3) foydalanuvchi komponentlarni erkin joylashtiradi — tartib, qo'shimcha element, o'rab oluvchi <div> qo'shishi mumkin (moslashuvchan — qattiq tuzilishga majburlamaydi). Ikki nuqta: (1) compound components — bog'liq komponentlar oilasi, holatni Context orqali yashirin ulashadi (foydalanuvchi Context haqida bilmaydi, faqat komponentlarni joylashtiradi); (2) qachon — Tab, Accordion, Menu, Select, Modal, RadioGroup kabi murakkab, ko'p-qismli UI uchun ideal. Bu — render props/hook qila olmaydi (UI komponentlari o'rtasida holat ulashish) — shuning uchun compound components hali ham eng yaxshi UI naqshi.

2.9. Compound components — Context bilan

text
  COMPOUND IMPLEMENTATSIYASI — Context bilan holatni yashirin ulashish (11.5: 2.11):

  const TabsContext = createContext();

  function Tabs({ children, defaultValue }) {
    const [active, setActive] = useState(defaultValue);
    return (
      <TabsContext.Provider value={{ active, setActive }}>   {/* holat ulashadi */}
        <div className="tabs">{children}</div>
      </TabsContext.Provider>
    );
  }

  function Tab({ value, children }) {
    const { active, setActive } = useContext(TabsContext);   // holatni oladi
    return (
      <button
        className={active === value ? "active" : ""}
        onClick={() => setActive(value)}
      >{children}</button>
    );
  }

  function Panel({ value, children }) {
    const { active } = useContext(TabsContext);
    return active === value ? <div>{children}</div> : null;   // faqat faol panel
  }

  // Bolalarni ota'ga "biriktirish" (Tabs.Tab — qulay API):
  Tabs.List = function ({ children }) { return <div className="tab-list">{children}</div>; };
  Tabs.Tab = Tab;
  Tabs.Panel = Panel;

   Context — compound'ning "yashirin sim"i (ota holatni bolalarga — foydalanuvchi bilmaydi)
   Tabs.Tab = Tab — bolalarni ota'ga biriktirish (qulay, guruhlangan API)

Compound components — Context bilan — implementatsiyaning yuragi. Compound components holatni Context (11.5: 2.11) orqali yashirin ulashadi. Tuzilishi: (1) TabsContext yaratiladi; (2) Tabs (ota) — active holatni saqlaydi va <TabsContext.Provider value={{ active, setActive }}> bilan bolalarga ulashadi; (3) Tab (bola) — useContext(TabsContext) bilan holatni oladi, bosilganda setActive(value); (4) Panel (bola) — faqat o'zining value'i faol bo'lganda render bo'ladi. Bolalarni ota'ga biriktirishTabs.Tab = Tab, Tabs.Panel = Panel (komponentga property sifatida) — bu qulay, guruhlangan API beradi (<Tabs.Tab> — foydalanuvchi Tab qayerga tegishliligini darrov ko'radi). Ikki nuqta: (1) Context — compound components'ning "yashirin sim"i: ota holatni bolalarga uzatadi, lekin foydalanuvchi Context haqida bilmaydi (faqat <Tabs>, <Tabs.Tab> joylashtiradi — ichki mexanizm yashirin); (2) Tabs.Tab = Tab — bolalarni ota'ga biriktirish (toza, guruhlangan API — Tabs.*). Bu naqsh — Radix UI, Reach UI, MUI kabi kutubxonalarning asosiy dizayni (ular compound components + Context'ga qurilgan). Bu — moslashuvchan, qayta ishlatiladigan UI komponentlari yaratishning eng kuchli usuli.

Eski usul — React.Children + cloneElement (Context'dan oldin). Context keng tarqalmasidan avval compound components holatni bolalarga React.Children.map bilan aylanib chiqib, har biriga cloneElement(child, { active, setActive }) orqali props "qo'shib" berardi:

jsx
function Tabs({ children, defaultValue }) {
  const [active, setActive] = useState(defaultValue);
  return React.Children.map(children, (child) =>
    React.cloneElement(child, { active, setActive })   // har bolaga qo'lda props "in'ektsiya"
  );
}

Bu usulning jiddiy kamchiliklari bor: (1) faqat bevosita bolalar props oladi — agar <Tab> bir <div> ichiga o'ralsa, cloneElement unga yeta olmaydi (chuqurroqda "yo'qoladi"); (2) props'lar aniq ko'rinmaydi (implicit — qaysi bola qaysi prop'ni oladi noaniq); (3) TypeScript bilan turini to'g'rilash og'ir. Context yechimi (yuqoridagi zamonaviy usul) bularning hammasini hal qiladi: bolalar istalgan chuqurlikda bo'lishi mumkin (useContext daraxt bo'ylab yuqoriga qaraydi), tuzilish erkin, tur tabiiy. Shuning uchun zamonaviy compound components — cloneElement emas, Context bilan yoziladi; cloneElement'ni asosan eski kodni o'qish uchun bilib qo'ying.

2.10. Control props va state reducer (ilg'or)

text
  CONTROL PROPS — komponent holatini OTA boshqarsin (controlled — 11.4: 2.11 g'oya):

  // Uncontrolled (komponent o'z holatini boshqaradi):
  <Tabs defaultValue="profil">...</Tabs>

  // Controlled (ota holatni boshqaradi — value + onChange):
  <Tabs value={active} onChange={setActive}>...</Tabs>
  //  ota qaysi tab faolligini NAZORAT qiladi (forma/URL bilan sinxron — 11.9 useSearchParams)

  HAR IKKALASINI qo'llab-quvvatlash (moslashuvchan komponent):
  function Tabs({ value, defaultValue, onChange, children }) {
    const [internal, setInternal] = useState(defaultValue);
    const active = value !== undefined ? value : internal;   // controlled yoki internal
    const setActive = (v) => { setInternal(v); onChange?.(v); };
    // ...
  }

  STATE REDUCER (eng ilg'or — Kent C. Dodds) — foydalanuvchi HOLAT MANTIG'INI o'zgartira olsin:
  <Tabs stateReducer={(state, action) => /* o'z qoidang */} >   // holat o'zgarishiga aralashish

   Control props — komponent ham mustaqil, ham boshqariladigan (eng moslashuvchan API)
   State reducer — kutubxona foydalanuvchisiga holat ustidan NAZORAT (ilg'or, kam)

Control props va state reducer — compound components'ning ilg'or moslashuvchanlik naqshlari. Control props — komponent holatini ota boshqarishiga imkon (controlled — 11.4: 2.11 g'oyasi). Ikki rejim: uncontrolled (<Tabs defaultValue="profil"> — komponent o'z holatini boshqaradi) va controlled (<Tabs value={active} onChange={setActive}> — ota holatni nazorat qiladi, masalan tab holatini URL bilan sinxronlash — 11.9 useSearchParams). Yaxshi komponent ikkalasini ham qo'llab-quvvatlaydi: ichida value !== undefined ? value : internalvalue prop berilsa controlled, aks holda ichki holat (<input>ning controlled/uncontrolled mexanizmidek). State reducer (eng ilg'or — Kent C. Dodds naqshi) — komponentga stateReducer prop berib, foydalanuvchi holat o'zgarish mantig'iga aralashishiga imkon beradi (masalan "bu tab'ni tanlashni taqiqla"). Ikki nuqta: (1) control props — komponent ham mustaqil (uncontrolled — oddiy), ham boshqariladigan (controlled — moslashuvchan) bo'lishiga imkon beradi (eng yaxshi API dizayni); (2) state reducer — kutubxona foydalanuvchisiga holat ustidan to'liq nazorat (ilg'or, kam ishlatiladi, lekin Downshift kabi murakkab kutubxonalarda mavjud). Bular — kutubxona darajasidagi moslashuvchan komponent dizaynining cho'qqisi.

2.11. Prop getters va qachon qaysi pattern

text
  PROP GETTERS — komponent kerakli props'ni "tayyorlab" beradi (kutubxonada keng — Downshift):
  const { getInputProps, getItemProps } = useCombobox(...);
  <input {...getInputProps()} />              // barcha kerakli prop (onChange, aria, ref) tayyor
  <li {...getItemProps({ item })} />          // moslashuvchan + to'g'ri (a11y, hodisalar)

  QAYSI PATTERN QACHON (xulosa):
  ┌──────────────────┬──────────────────────────────────────────┐
  │ MANTIQ ulashish   │ custom hook 11.7-bob — DEFAULT (zamonaviy)  │
  │ UI komponent oilasi│ compound components (Tab/Accordion — 2.9)│
  │ Komponentni o'rash │ HOC (kam — error boundary, analytics)    │
  │ UI'ga bog'liq mantiq│ render props (o'lcham, virtualization)  │
  │ Moslashuvchan API │ control props + prop getters (kutubxona) │
  └──────────────────┴──────────────────────────────────────────┘

   Zamonaviy default: custom hook (mantiq) + compound components (UI oilasi)
   HOC/render props — asosan ESKI kod va MAXSUS holatlar (tushunish uchun bil)

Prop getters va qachon qaysi pattern — yakuniy xulosa. Prop getters — komponent foydalanuvchiga kerakli props'ni tayyorlab beradigan naqsh (kutubxonalarda keng — Downshift, React Table): const { getInputProps } = useCombobox(...) <input {...getInputProps()} /> — barcha kerakli prop (onChange, aria-*, ref, hodisalar) avtomatik tayyorlangan va to'g'ri (a11y, kuzatuv) — foydalanuvchi faqat spread qiladi (moslashuvchan + xatosiz). Qaysi pattern qachon (eng muhim xulosa): mantiq ulashish custom hook (default, zamonaviy — 11.7); UI komponentlar oilasi (Tab, Accordion, Select) compound components 2.9-bob; komponentni butunlay o'rash (error boundary, analytics tracking) HOC (kam); UI'ga bog'liq mantiq (o'lcham, virtualization) render props; moslashuvchan kutubxona API control props + prop getters. Ikki yakuniy nuqta: (1) zamonaviy default — custom hook (mantiq) + compound components (UI oilasi) — ko'p holda shu ikkisi yetadi; (2) HOC/render props — asosan eski kod va maxsus holatlar uchun (lekin ularni o'qiy va tushuna olish kerak — ko'p mavjud kod va kutubxona ishlatadi). Bu naqshlarning hammasini bilish — har qanday React kodni o'qiy olish va to'g'ri dizayn tanlashning kalitidir.

2.12. Provider pattern

text
  PROVIDER PATTERN — global holat/xizmatni Context orqali daraxtga ulashish (12-QISM state):

  const ThemeContext = createContext();
  function ThemeProvider({ children }) {
    const [theme, setTheme] = useState("light");
    const toggle = () => setTheme(t => t === "light" ? "dark" : "light");
    return (
      <ThemeContext.Provider value={{ theme, toggle }}>{children}</ThemeContext.Provider>
    );
  }
  function useTheme() {                          // provider bilan birga custom hook (qulay API)
    const ctx = useContext(ThemeContext);
    if (!ctx) throw new Error("useTheme <ThemeProvider> ichida bo'lishi kerak");
    return ctx;
  }

  // Ilova ildizida bir marta:  <ThemeProvider><App/></ThemeProvider>
  // Istalgan chuqurlikda:      const { theme, toggle } = useTheme();

   Provider + custom hook — global holat ulashishning standart jufti (theme, auth, i18n)
   Compound Context'dan farqi: Provider ILOVA darajasida (global), compound bitta komponent oilasida

Provider pattern — global holat yoki xizmatni butun daraxtga (yoki uning bir qismiga) Context orqali ulashish naqshi. Bu compound components'dagi Context bilan bir xil mexanizm, lekin miqyosi boshqacha: compound Context bir komponent oilasi ichida (<Tabs> ichida), Provider pattern esa ilova darajasida (theme, autentifikatsiya, til/i18n, bildirishnoma, savatcha). Tuzilishi ikki qismdan iborat: (1) Provider komponenti — holatni saqlaydi va <Context.Provider> bilan ulashadi (<ThemeProvider>), ilova ildizida bir marta joylashtiriladi; (2) maxsus custom hook — Context'ni o'qishning qulay va xavfsiz usuli (useTheme()), ichida if (!ctx) throw bilan Provider tashqarisida ishlatilsa aniq xato beradi (undefined bilan jimgina buzilish o'rniga). Ikki nuqta: (1) Provider + custom hook jufti — React'da global holat ulashishning de-fakto standarti (ko'p kutubxona — React Query, Redux, React Router — shu naqshda <QueryClientProvider>, <Provider> beradi); (2) bu — Context'ni to'g'ridan-to'g'ri ishlatishdan afzal, chunki hook API'ni yashiradi va nazoratni beradi (masalan keyin Context ichki tuzilishini o'zgartirsangiz, faqat hook'ni yangilaysiz, foydalanuvchi kodi tegmaydi). 12-QISM'da bu naqsh (Context + provider) holat boshqaruvining asosi sifatida chuqurroq ko'riladi.

2.13. Presentational vs Container (eski naqsh — hook'lar bilan o'zgargan)

text
  ESKI NAQSH (Dan Abramov, 2015) — mas'uliyatni ikki komponentga ajratish:

  CONTAINER (aqlli) — MANTIQ: state, data fetching, event handler'lar (UI yo'q):
  function UserListContainer() {
    const { data, loading } = useFetch("/api/users");
    return <UserListView users={data} loading={loading} />;   // faqat UI'ga props uzatadi
  }
  PRESENTATIONAL (soqov) — faqat UI: props oladi, chizadi (state/effect yo'q):
  function UserListView({ users, loading }) {
    if (loading) return <Spinner/>;
    return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
  }

   HOOK'LAR BUNI O'ZGARTIRDI: mantiq endi custom hook'da (alohida komponent shart emas)
   function UserList() { const {data} = useUsers(); return <ul>...</ul>; }  // bitta komponent yetadi

Presentational vs Container — hook'lardan oldingi mashhur naqsh (Dan Abramov, 2015): har bir "ekran"ni ikki komponentga ajratish — container (aqlli — state, data fetching, event handler; UI'ni deyarli chizmaydi) va presentational (soqov — faqat props oladi va chizadi, o'z holati/effekti yo'q). Maqsad — mas'uliyatni ajratish (9-QISM SoC): UI mantiqdan mustaqil (osonroq test, qayta ishlatish, dizayner ishlashi mumkin). Masalan UserListContainer ma'lumotni oladi va UserListView'ga props sifatida beradi; UserListView esa faqat chizadi. Muhim yangilik: custom hook'lar bu naqshni asosan o'zgartirdi. Endi mantiqni alohida komponentga ajratish shart emas — uni custom hookga ajratish yetarli (function UserList() { const { data, loading } = useUsers(); ... }). Mantiq hook'da (qayta ishlatiladigan, test qilinadigan), UI komponentda — ikkisi bitta faylda, ammo baribir ajratilgan. Shuning uchun zamonaviy React'da toza "presentational/container" ajratmasi kamayadi; uning o'rnini "UI komponent + custom hook" egalladi. Naqshning g'oyasi (mantiq va ko'rinishni ajratish) esa hali ham to'g'ri va qimmatli — faqat vositasi (ikki komponent hook) o'zgardi.

2.14. Polymorphic komponent (as prop)

text
  POLYMORPHIC KOMPONENT — qaysi HTML teg/komponent sifatida render bo'lishini `as` prop hal qiladi:

  function Text({ as: Component = "span", children, ...props }) {
    return <Component {...props}>{children}</Component>;   // "as" — qaysi teg
  }
  <Text>oddiy span</Text>
  <Text as="h1">sarlavha</Text>              // <h1> sifatida
  <Text as="label" htmlFor="email">Email</Text>
  <Text as={Link} to="/uy">Bosh sahifa</Text>   // hatto boshqa komponent sifatida ham

  TS bilan (turini "as"ga moslash — ilg'or):
  type TextProps<T extends React.ElementType> =
    { as?: T; children: React.ReactNode } & React.ComponentPropsWithoutRef<T>;
  // <Text as="a" href="..."/>   href tekshiriladi; <Text as="button" href/>  TS xatosi

   Polymorphic — bitta komponent, ko'p teg (Button/Text/Box — dizayn tizimlarida keng)
   TS bilan to'g'ri qilish murakkab (generic + ComponentPropsWithoutRef) — 11.14

Polymorphic komponent — bitta komponent turli HTML teg yoki boshqa komponent sifatida render bo'lishiga imkon beradigan naqsh; qaysi teg ekanini as prop hal qiladi. function Text({ as: Component = "span", ...props }) { return <Component {...props} /> } — odatda <span>, lekin <Text as="h1">, <Text as="label">, hatto <Text as={Link}> (React Router Link) sifatida ham ishlaydi. Bu — dizayn tizimlarida (design system) juda keng: Box, Text, Button kabi asosiy komponentlar bitta uslub/mantiq bilan, lekin turli semantik teglar bilan ishlatiladi (masalan <Button as="a" href="..."> — ko'rinishi tugma, semantikasi havola). Ikki nuqta: (1) polymorphic komponent kod takrorini kamaytiradi (har teg uchun alohida komponent yozmaysiz) va a11y'ni yaxshilaydi (to'g'ri semantik teg tanlash imkoni); (2) TypeScript bilan to'g'ri turlash murakkabas prop qiymatiga qarab ruxsat etilgan props o'zgaradi (as="a" href bor, as="button" href yo'q). Buni generic (<T extends React.ElementType>) va React.ComponentPropsWithoutRef<T> bilan ifodalanadi — bu mavzu 11.14 (TypeScript bilan React) da chuqurroq ko'riladi. Polymorphic komponent — yana bir isbot: React'da to'g'ri primitivlar (asosiy komponentlar) qurish keyingi hamma narsani soddalashtiradi.


3. Sintaksis — tez ma'lumotnoma

text
KOMPOZITSIYA (2.1b): function Card({children}){<div>{children}</div>}  |  <List ItemComponent={Row}/>
SLOT (2.1b):         function L({header,children}){...}    <L header={<Nav/>}>...</L>
HOC 2.2-bob:           function withX(Comp) { return (props) => <Comp {...props} extra={...}/> }
                     const Enhanced = withX(MyComp)
HOC ref (2.3b):      forwardRef((props,ref)=><Comp ref={ref} {...props}/>); W.displayName=`withX(...)`
RENDER PROPS 2.5-bob:  function X({ render }) { return render(data) }    <X render={d => <UI/>}/>
CHILDREN FN 2.6-bob:   function X({ children }) { return children(data) }    <X>{d => <UI/>}</X>
COMPOUND 2.9-bob:      const Ctx=createContext(); function Parent({children}){<Ctx.Provider>...}
                     Parent.Child = Child;    <Parent><Parent.Child/></Parent>
CONTROL PROPS 2.10-bob:value!==undefined ? value : internal   // controlled yoki uncontrolled
PROP GETTERS 2.11-bob: const { getInputProps } = useX();  <input {...getInputProps()}/>
PROVIDER 2.12-bob:     function XProvider({children}){<Ctx.Provider value={v}>{children}</Ctx.Provider>}
POLYMORPHIC 2.14-bob:  function Text({as:C="span",...p}){return <C {...p}/>}    <Text as="h1"/>
QAYSI 2.11-bob:        mantiqhook | UI oilasicompound | o'rashHOC | UI mantiqrender props

4. Batafsil kod namunalari

Misol 1 — HOC: withLoading (2.2, 2.3)

jsx
function withLoading(Component) {
  return function WithLoading({ isLoading, ...props }) {
    if (isLoading) return <Spinner />;          // qo'shimcha mantiq
    return <Component {...props} />;            // asl komponent (props uzatiladi)
  };
}

function UserList({ users }) {
  return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

const UserListWithLoading = withLoading(UserList);   // kuchaytirilgan versiya
// Ishlatish: <UserListWithLoading isLoading={loading} users={users} />
//  isLoading bo'lsa Spinner, aks holda UserList (HOC mantiq qo'shdi — 2.2)

Misol 2 — HOC: withAuth (himoya — 2.3)

jsx
import { Navigate } from "react-router-dom";

function withAuth(Component) {
  return function WithAuth(props) {
    const { user, loading } = useAuth();        // 11.7
    if (loading) return <Spinner />;
    if (!user) return <Navigate to="/login" replace />;   // himoya (11.9)
    return <Component {...props} user={user} />;          // user prop qo'shadi
  };
}

const ProtectedDashboard = withAuth(Dashboard);
//  Dashboard endi himoyalangan + user prop oladi (eski React'da keng — endi ProtectedRoute 11.9)

Misol 3 — HOC kompozitsiyasi va muammosi (2.4)

jsx
//  Wrapper hell — ichma-ich HOC (chalkash, DevTools'da shovqin):
const Enhanced = withAuth(withLoading(withTheme(withAnalytics(MyComponent))));
//               4 qatlam — qaysi prop qayerdan? to'qnashuv? (2.4)

//  Custom hook — yassi, manba aniq (zamonaviy yechim):
function MyComponent() {
  const { user } = useAuth();          // manba aniq
  const theme = useTheme();            // to'qnashuv yo'q
  useAnalytics("MyComponent");
  return <div>...</div>;
}
//  Mantiq uchun — HOC kompozitsiyasi EMAS, custom hook (11.7, 2.4)

Misol 4 — Render props: MouseTracker (2.5)

jsx
function MouseTracker({ render }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  useEffect(() => {
    const onMove = (e) => setPos({ x: e.clientX, y: e.clientY });
    window.addEventListener("mousemove", onMove);
    return () => window.removeEventListener("mousemove", onMove);
  }, []);
  return render(pos);                  // mantiqni (pos) funksiyaga beradi
}

// Bir xil mantiq, har xil UI:
<MouseTracker render={(pos) => <p>Sichqoncha: {pos.x}, {pos.y}</p>} />
<MouseTracker render={(pos) => <div style={{ left: pos.x, top: pos.y }} className="cursor" />} />
//  Mantiq (kuzatish) MouseTracker'da; UI chaqiruvchida (moslashuvchan — 2.5)

Misol 5 — Children as function: Toggle (2.6)

jsx
function Toggle({ children }) {
  const [on, setOn] = useState(false);
  const toggle = () => setOn(o => !o);
  return children({ on, toggle });     // children — funksiya
}

// Ishlatish:
<Toggle>
  {({ on, toggle }) => (
    <div>
      <button onClick={toggle}>{on ? " Yoqilgan" : " O'chiq"}</button>
      {on && <p>Bildirishnomalar yoqilgan</p>}
    </div>
  )}
</Toggle>
//  children funksiya — mantiq Toggle'da, UI funksiyada (render props turi — 2.6)

Misol 6 — Render props custom hook (2.7)

jsx
// ESKI (render props):
// <MouseTracker render={(pos) => <UI pos={pos}/>} />

// ZAMONAVIY (custom hook — 11.7):
function useMouse() {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  useEffect(() => {
    const onMove = (e) => setPos({ x: e.clientX, y: e.clientY });
    window.addEventListener("mousemove", onMove);
    return () => window.removeEventListener("mousemove", onMove);
  }, []);
  return pos;
}

function Component() {
  const pos = useMouse();              // yassi — ichma-ich yo'q (2.7)
  const theme = useTheme();
  return <div>{pos.x}, {pos.y}</div>;
}
//  Hook — render props piramidasini yo'qotadi (mantiq uchun afzal — 2.7)

Misol 7 — Compound components: Tabs (2.8, 2.9)

jsx
import { createContext, useContext, useState } from "react";

const TabsContext = createContext();

function Tabs({ children, defaultValue }) {
  const [active, setActive] = useState(defaultValue);
  return (
    <TabsContext.Provider value={{ active, setActive }}>
      <div className="tabs">{children}</div>
    </TabsContext.Provider>
  );
}

function TabList({ children }) { return <div className="tab-list" role="tablist">{children}</div>; }

function Tab({ value, children }) {
  const { active, setActive } = useContext(TabsContext);
  return (
    <button role="tab" aria-selected={active === value}
      className={active === value ? "active" : ""}
      onClick={() => setActive(value)}>{children}</button>
  );
}

function Panel({ value, children }) {
  const { active } = useContext(TabsContext);
  return active === value ? <div role="tabpanel">{children}</div> : null;
}

// Bolalarni ota'ga biriktirish (qulay API):
Tabs.List = TabList;
Tabs.Tab = Tab;
Tabs.Panel = Panel;

// Ishlatish — moslashuvchan, o'qish oson:
function App() {
  return (
    <Tabs defaultValue="profil">
      <Tabs.List>
        <Tabs.Tab value="profil">Profil</Tabs.Tab>
        <Tabs.Tab value="sozlama">Sozlamalar</Tabs.Tab>
      </Tabs.List>
      <Tabs.Panel value="profil">Profil kontenti</Tabs.Panel>
      <Tabs.Panel value="sozlama">Sozlamalar kontenti</Tabs.Panel>
    </Tabs>
  );
}
//  Holat Context'da yashirin ulashiladi; foydalanuvchi erkin joylashtiradi (2.9)

Misol 8 — Compound: Accordion (2.9)

jsx
const AccordionContext = createContext();

function Accordion({ children }) {
  const [openId, setOpenId] = useState(null);
  const toggle = (id) => setOpenId(prev => (prev === id ? null : id));   // bittasi ochiq
  return (
    <AccordionContext.Provider value={{ openId, toggle }}>
      <div className="accordion">{children}</div>
    </AccordionContext.Provider>
  );
}

function Item({ id, title, children }) {
  const { openId, toggle } = useContext(AccordionContext);
  const isOpen = openId === id;
  return (
    <div className="acc-item">
      <button onClick={() => toggle(id)} aria-expanded={isOpen}>{title} {isOpen ? "▲" : "▼"}</button>
      {isOpen && <div className="acc-content">{children}</div>}
    </div>
  );
}
Accordion.Item = Item;

// <Accordion><Accordion.Item id="1" title="Savol 1">Javob</Accordion.Item></Accordion>

Misol 9 — Control props (controlled + uncontrolled — 2.10)

jsx
function Tabs({ value, defaultValue, onChange, children }) {
  const [internal, setInternal] = useState(defaultValue);
  const active = value !== undefined ? value : internal;   // controlled yoki internal
  const setActive = (v) => {
    if (value === undefined) setInternal(v);   // uncontrolled — ichki holat
    onChange?.(v);                              // controlled — otaga xabar
  };
  return (
    <TabsContext.Provider value={{ active, setActive }}>
      <div className="tabs">{children}</div>
    </TabsContext.Provider>
  );
}

// Uncontrolled: <Tabs defaultValue="a">...
// Controlled (URL bilan — 11.9): <Tabs value={tab} onChange={setTab}>...
//  Bitta komponent — ham mustaqil, ham boshqariladigan (moslashuvchan API — 2.10)

Misol 10 — Prop getters (2.11)

jsx
// Custom hook prop getters qaytaradi (Downshift uslubi):
function useAccordion() {
  const [open, setOpen] = useState(false);
  return {
    isOpen: open,
    getButtonProps: () => ({           // tugma uchun tayyor props
      onClick: () => setOpen(o => !o),
      "aria-expanded": open,
    }),
    getPanelProps: () => ({             // panel uchun tayyor props
      hidden: !open,
      role: "region",
    }),
  };
}

function FAQ() {
  const { isOpen, getButtonProps, getPanelProps } = useAccordion();
  return (
    <div>
      <button {...getButtonProps()}>Savol {isOpen ? "▲" : "▼"}</button>   {/* a11y/hodisa tayyor */}
      <div {...getPanelProps()}>Javob</div>
    </div>
  );
}
//  Prop getters — kerakli props (hodisa, a11y) tayyor; foydalanuvchi spread qiladi (2.11)

Misol 11 — HOC (maxsus holat: error boundary HOC — 2.11)

jsx
import { ErrorBoundary } from "react-error-boundary";

// HOC hali foydali: komponentni butunlay o'rab (error boundary — 11.12)
function withErrorBoundary(Component, fallback) {
  return function (props) {
    return (
      <ErrorBoundary fallback={fallback}>
        <Component {...props} />
      </ErrorBoundary>
    );
  };
}

const SafeWidget = withErrorBoundary(Widget, <p>Widget xato</p>);
//  HOC mantiq uchun kam, lekin "o'rab olish" (error boundary, analytics) uchun hali qulay (2.11)

Misol 12 — Pattern'larni solishtirish (bir mantiq, 3 usul — 2.7)

jsx
// Bir xil "toggle" mantig'i — 3 pattern:

// 1. Custom hook (zamonaviy — DEFAULT):
function useToggle() { const [on, setOn] = useState(false); return [on, () => setOn(o => !o)]; }

// 2. Render props (children function):
function Toggle({ children }) { const [on, setOn] = useState(false); return children({ on, toggle: () => setOn(o => !o) }); }

// 3. HOC:
function withToggle(C) { return (props) => { const [on, setOn] = useState(false); return <C {...props} on={on} toggle={() => setOn(o => !o)} />; }; }

//  Bir mantiq, 3 usul. Zamonaviy: hook (1). Eski: render props (2), HOC (3) — 2.7, 2.11

Misol 13 — Compound + render props birga (moslashuvchan — 2.9, 2.6)

jsx
// Ba'zan compound + render props birga (eng moslashuvchan):
function Select({ children, defaultValue }) {
  const [value, setValue] = useState(defaultValue);
  const [open, setOpen] = useState(false);
  return (
    <SelectContext.Provider value={{ value, setValue, open, setOpen }}>
      {children}
    </SelectContext.Provider>
  );
}

function SelectTrigger({ children }) {
  const { value, open, setOpen } = useContext(SelectContext);
  return (
    <button onClick={() => setOpen(o => !o)}>
      {typeof children === "function" ? children({ value, open }) : children}  {/* render props ham */}
    </button>
  );
}
Select.Trigger = SelectTrigger;
// <Select.Trigger>{({ value }) => `Tanlangan: ${value}`}</Select.Trigger>  // render props moslashuvchanlik

Misol 14 — Qaysi pattern qachon (qaror jadvali — 2.11)

jsx
// MANTIQ ulashish (state, effect, data)  CUSTOM HOOK:
function Component() { const data = useFetch(url); /* ... */ }

// UI KOMPONENT OILASI (Tab/Accordion/Select)  COMPOUND COMPONENTS:
<Tabs><Tabs.Tab/><Tabs.Panel/></Tabs>

// KOMPONENTNI O'RASH (error boundary, analytics)  HOC:
const Safe = withErrorBoundary(Component);

// UI'GA BOG'LIQ MANTIQ (o'lcham, virtualization)  RENDER PROPS:
<Measure>{({ width }) => <Chart width={width}/>}</Measure>

// MOSLASHUVCHAN KUTUBXONA API  CONTROL PROPS + PROP GETTERS:
const { getInputProps } = useCombobox();
//  To'g'ri pattern — muammoga mos (hook default; compound UI; HOC/render props maxsus — 2.11)

Misol 15 — Kompozitsiya: children, slot, komponent prop (2.1b)

jsx
// 1. children — o'rash (HOC'siz):
function Card({ title, children }) {
  return (
    <div className="card">
      {title && <h3 className="card-title">{title}</h3>}
      <div className="card-body">{children}</div>
    </div>
  );
}

// 2. slot — nomlangan JSX prop:
function PageLayout({ header, sidebar, children }) {
  return (
    <div className="layout">
      <header>{header}</header>
      <aside>{sidebar}</aside>
      <main>{children}</main>
    </div>
  );
}

// 3. komponent prop — qaysi komponent chizishini chaqiruvchi hal qiladi:
function List({ items, ItemComponent }) {
  return <ul>{items.map((x) => <ItemComponent key={x.id} item={x} />)}</ul>;
}

function App() {
  return (
    <PageLayout header={<Navbar />} sidebar={<Menu />}>
      <Card title="Foydalanuvchilar">
        <List items={users} ItemComponent={UserCard} />
      </Card>
    </PageLayout>
  );
}
//  Kompozitsiya ko'p muammoni HOC'siz/Context'siz hal qiladi — birinchi shuni o'ylang (2.1b)

Misol 16 — HOC: displayName + ref forwarding (2.3b)

jsx
import { forwardRef } from "react";

function withLoading(Component) {
  const WithLoading = forwardRef(function WithLoading({ isLoading, ...props }, ref) {
    if (isLoading) return <Spinner />;
    return <Component ref={ref} {...props} />;   // ref asl komponentga o'tadi
  });
  const name = Component.displayName || Component.name || "Component";
  WithLoading.displayName = `withLoading(${name})`;   // DevTools: withLoading(Input)
  return WithLoading;
}

const InputWithLoading = withLoading(Input);
// <InputWithLoading ref={inputRef} isLoading={loading} placeholder="Ism" />
//  forwardRef'siz ref wrapper'ga tegardi; displayName DevTools daraxtini tushunarli qiladi (2.3b)

Misol 17 — Provider pattern (Context + custom hook — 2.12)

jsx
import { createContext, useContext, useState } from "react";

const ThemeContext = createContext(null);

function ThemeProvider({ children }) {
  const [theme, setTheme] = useState("light");
  const toggle = () => setTheme((t) => (t === "light" ? "dark" : "light"));
  return (
    <ThemeContext.Provider value={{ theme, toggle }}>
      {children}
    </ThemeContext.Provider>
  );
}

function useTheme() {
  const ctx = useContext(ThemeContext);
  if (!ctx) throw new Error("useTheme <ThemeProvider> ichida chaqirilishi kerak");
  return ctx;   // { theme, toggle }
}

// Ildizda: <ThemeProvider><App /></ThemeProvider>
function ThemeButton() {
  const { theme, toggle } = useTheme();   // istalgan chuqurlikda, xavfsiz
  return <button onClick={toggle}>Mavzu: {theme}</button>;
}
//  Provider + custom hook — global holat (theme/auth/i18n) ulashishning standart jufti (2.12)

Misol 18 — Polymorphic komponent (as prop — 2.14)

jsx
function Text({ as: Component = "span", ...props }) {
  return <Component {...props} />;   // qaysi teg — "as" hal qiladi
}

// Bir komponent, ko'p teg:
<Text>oddiy matn</Text>                      {/* <span> */}
<Text as="h1" className="title">Sarlavha</Text>   {/* <h1>  */}
<Text as="label" htmlFor="email">Email</Text>     {/* <label htmlFor> */}
<Text as={Link} to="/uy">Bosh sahifa</Text>       {/* React Router Link sifatida */}
//  Dizayn tizimlarida keng (Box/Text/Button); TS bilan turlash — 11.14 (2.14)

5. To'g'ri va noto'g'ri holatlar

1) Mantiq ulashish

text
 HOC/render props (wrapper hell / piramida — 2.4, 2.7)
 custom hook (yassi, manba aniq — 11.7)

2) UI komponent oilasi

text
 bitta katta komponent + ko'p props (Tabs items prop bilan — qattiq)
 compound components (Tabs.Tab — moslashuvchan, Context — 2.9)

3) HOC props

text
 HOC props'ni uzatmaslik (<Component user={user}/> — boshqa props yo'qoladi)
 <Component {...props} user={user}/> (mavjudni saqla — 2.3)

4) Compound holat

text
 holatni har bolaga props bilan (drilling — qattiq)
 Context bilan yashirin ulash (foydalanuvchi bilmaydi — 2.9)

5) Control props

text
 faqat uncontrolled (URL/forma bilan sinxron qilib bo'lmaydi)
 controlled + uncontrolled ikkalasi (moslashuvchan — 2.10)

6) Pattern tanlovi

text
 hamma narsaga HOC (eski tafakkur — wrapper hell)
 muammoga mos: hook (mantiq), compound (UI), HOC (o'rash) — 2.11

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — HOC props yo'qoladi (asl komponent props olmaydi)

Sababi: {...props} uzatilmadi 2.3-bob. Yechimi: <Component {...props} extra={...} />.

Xato 2 — Wrapper hell (ko'p HOC — debug qiyin)

Sababi: mantiq uchun HOC kompozitsiyasi 2.4-bob. Yechimi: custom hook'ga ko'chir (Misol 3, 11.7).

Xato 3 — Compound component Context'siz ishlamaydi (Cannot read context)

Sababi: Tabs.Tab <Tabs> tashqarisida ishlatildi (Context yo'q — 2.9). Yechimi: bolalarni har doim ota ichida; hook'da tekshir (if (!ctx) throw).

Xato 4 — Render props piramida (ichma-ich, o'qish qiyin)

Sababi: ko'p render props ichma-ich 2.7-bob. Yechimi: custom hook'ga aylantir (Misol 6).

Xato 5 — Compound bolalar tartibi/joyi qattiq

Sababi: ota childrenni qattiq kutadi (faqat aniq tuzilish). Yechimi: Context bilan — bolalar erkin joylashsin (childrenni filter qilma — 2.9).

Xato 6 — Controlled/uncontrolled aralashib ketdi

Sababi: value ham, defaultValue ham, yoki ikkalasi noto'g'ri 2.10-bob. Yechimi: value !== undefined ? value : internal mantig'i (Misol 9).

Xato 7 — HOC TypeScript turlari yo'qoladi

Sababi: HOC props turini saqlamaydi 2.4-bob. Yechimi: custom hook (tur tabiiy saqlanadi), yoki HOC generics (murakkab).


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • Custom hooks 11.7-bob: HOC/render props'ning zamonaviy muqobili (mantiq uchun).
  • Kompozitsiya 11.2-bob: children/slot/komponent prop — HOC'siz qayta ishlatish (2.1b).
  • Context (11.5: 2.11): compound components va provider pattern'ning yuragi (yashirin holat ulash).
  • State boshqaruvi (12-QISM): provider pattern — global holat (theme/auth) ulashish 2.12-bob.
  • Controlled inputs (11.4: 2.11): control props — komponent darajasida bir xil g'oya.
  • forwardRef 11.6-bob: HOC ref forwarding — ref'ni asl komponentga o'tkazish (2.3b).
  • Error boundary 11.12-bob: HOC maxsus holat (withErrorBoundary — Misol 11).
  • Routing 11.9-bob: protected route — withAuth HOC'ning zamonaviy ko'rinishi.
  • UI kutubxonalar 12.6-bob: Radix/MUI/Headless — compound + prop getters'ga qurilgan.
  • TypeScript 11.14-bob: compound/hook — turlar tabiiy; HOC — murakkab generics.
  • a11y 1.9-bob: compound (Tabs role/aria) — prop getters a11y'ni tayyorlaydi.

8. Eng yaxshi amaliyotlar (best practices)

  • Avval kompozitsiya (children/slot/komponent prop — HOC/Context'dan oldin o'ylang — 2.1b).
  • Mantiq custom hook (HOC/render props emas — zamonaviy default — 2.4, 2.7).
  • UI oilasi compound components (Tab/Accordion/Select — moslashuvchan — 2.9).
  • Compound — Context bilan, cloneElement emas (chuqur bolalar, tur tabiiy — 2.9).
  • HOC — displayName + forwardRef (DevTools tushunarli, ref o'tsin — 2.3b).
  • Global holat provider pattern (Context + custom hook jufti — 2.12).
  • Compound — Context bilan (holat yashirin ulash; bolalar erkin — 2.9).
  • HOC props'ni uzat ({...props} — mavjudni saqla — 2.3).
  • HOC faqat o'rash uchun (error boundary, analytics — mantiq emas — 2.11).
  • Control props (controlled + uncontrolled — moslashuvchan API — 2.10).
  • Prop getters (kutubxonada — a11y/hodisa tayyor — 2.11).
  • Pattern muammoga mos (hook/compound/HOC/render props — 2.11).
  • Eski pattern'larni o'qiy ol (HOC/render props — mavjud kod/kutubxona).
  • Kutubxona dizaynini o'rgan (Radix/Headless — compound + getter namunasi — 2.11).

9. Amaliy loyiha: "Qayta Ishlatiladigan UI Komponentlar To'plami"

Pattern'larni birlashtirib, moslashuvchan UI komponentlar kutubxonasini qurish.

Maqsad

Compound components, control props va prop getters bilan professional Tabs, Accordion va Select komponentlarini yaratish.

Talablar (requirements)

  1. Tabs (compound): <Tabs>, <Tabs.List>, <Tabs.Tab>, <Tabs.Panel> — Context bilan (Misol 7, 2.9).
  2. Accordion (compound): bir yoki ko'p element ochiq rejimi (Misol 8).
  3. Control props: Tabs ham controlled (value/onChange), ham uncontrolled (defaultValue) — URL bilan sinxron (Misol 9, 2.10, 11.9).
  4. Custom hook: kamida bitta mantiqni custom hook qil (useToggle/useDisclosure — Misol 12, 11.7).
  5. Prop getters: kamida bitta komponent prop getter qaytarsin (a11y tayyor — Misol 10, 2.11).
  6. a11y: compound komponentlar role/aria (tablist/tab/tabpanel — 1.9, 2.9).
  7. HOC (maxsus): withErrorBoundary HOC bilan komponentni o'rab himoyala (Misol 11, 11.12).
  8. Render props (moslashuvchan): kamida bitta joyda render props/children function (Misol 13, 2.6).
  9. Pattern tanlovi: har komponentda NEGA shu pattern'ni tanlaganingni izohla 2.11-bob.
  10. Qayta ishlatish: komponentlarni components/ui/da, real sahifada ishlat.

Maslahatlar (hint)

  • Compound — Context bilan (holat yashirin); Tabs.Tab = Tab bilan biriktir (Misol 7).
  • Bolalarni <Tabs> ichida ishlatishni hook'da tekshir (Context yo'q bo'lsa xato — Xato 3).
  • Control props: value !== undefined ? value : internal (Misol 9, 2.10).
  • Mantiq uchun custom hook; UI oilasi uchun compound (aralashtirma — 2.11).
  • a11y'ni boshidan (role/aria) — Radix/Headless namunasini ko'r 2.11-bob.
  • HOC faqat "o'rash" uchun (error boundary) — mantiq uchun hook (Misol 11, 2.4).

"Tayyor" mezonlari (acceptance criteria)

  • Tabs compound (List/Tab/Panel — Context).
  • Accordion compound (ochiq/yopiq).
  • Tabs controlled + uncontrolled (URL bilan sinxron).
  • Kamida bitta custom hook (mantiq).
  • Kamida bitta prop getter (a11y tayyor).
  • Compound a11y (role/aria).
  • withErrorBoundary HOC ishlatilgan.
  • Render props/children function kamida bir joyda.
  • Har pattern tanlovi oqlangan (NEGA — 2.11).

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda React'ning klassik va zamonaviy pattern'larini chuqur o'rgandik:

  • Nega pattern'lar (mantiq/UI qayta ishlatish — 2.1); kompozitsiya (children/slot/komponent prop — 2.1b).
  • HOC (nima — 2.2, qanday — 2.3, displayName/ref/props forwarding — 2.3b, muammolar — 2.4).
  • Render props (nima — 2.5, children function — 2.6, hooks bilan taqqos — 2.7).
  • Compound components (nima — 2.8, Context bilan (va eski cloneElement) — 2.9, control props/state reducer — 2.10, prop getters va qachon qaysi — 2.11).
  • Provider pattern 2.12-bob, presentational vs container 2.13-bob, polymorphic komponent (as prop — 2.14).

Endi siz har qanday React kodni o'qiy olasiz (HOC/render props bo'lsa ham), va to'g'ri pattern tanlay olasiz: mantiq uchun custom hook, UI oilasi uchun compound components, maxsus holatlar uchun HOC/render props. Eng muhimi — UI kutubxonalar (Radix, MUI, Headless) qanday qurilganini tushunasiz.

Keyingi bob — 11.14-bob: TypeScript bilan React. 7-QISM'da TypeScript'ni o'rgandik — endi uni React bilan birlashtiramiz. Komponent va props turlari (interface/type, children, event), hooklar turlari (useState<T>, useRef, useReducer), generic komponentlar, event va form turlari, React.FC munozarasi, va 11.10'dagi Zod + TypeScript birikmasini chuqurlashtirish. TypeScript — zamonaviy professional React loyihasining standarti (xatolarni compile paytida tutadi, autocomplete, refactoring xavfsizligi).


Foydalanilgan rasmiy/ishonchli manbalar

  • React rasmiy hujjati (react.dev) — "Passing Props to a Component", "Passing Data Deeply with Context", "Sharing State Between Components" (kompozitsiya, children, Context)
  • React rasmiy hujjati (react.dev) — "Reusing Logic with Custom Hooks" (HOC/render props hook'larga o'tish)
  • React eski hujjati (legacy.reactjs.org) — "Higher-Order Components", "Render Props", "Composition vs Inheritance"
  • React rasmiy hujjati (react.dev) — forwardRef va ref forwarding (HOC'da ref uzatish)
  • Kent C. Dodds — "Advanced React Patterns" / EpicReact (compound components, control props, state reducer, prop getters)
  • Radix UI / Headless UI / Reach UI — compound components + prop getters + a11y arxitekturasi
  • Chakra UI / Stitches — polymorphic komponent (as prop) dizayni
  • Dan Abramov — "Presentational and Container Components" (naqsh va hook'lardan keyingi holati)

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
11.13-bob: React pattern'lar — HOC, render props, compound components — Wisar