WisarWisar
Dasturlash kitobi/11-QISM — React44 daqiqa

11.9-bob: Routing (React Router)

11-QISM — Frontend: React · 9-mavzu


1. Kirish va motivatsiya

Shu paytgacha yozgan ilovalarimiz bitta ekrandan iborat edi. Lekin haqiqiy ilova — ko'p sahifali: bosh sahifa, mahsulotlar, mahsulot tafsiloti, savat, profil, sozlamalar, login... Foydalanuvchi /products manziliga o'tsa mahsulotlar, /cart ga o'tsa savat ko'rinishi kerak. Bundan tashqari — foydalanuvchi URL'ni ko'chirib do'stiga yuborsa, "orqaga" tugmasini bossa, sahifani yangilasa — hammasi kutilgandek ishlashi lozim. Bu — routing (yo'naltirish): URL'ni (manzilni) UI bilan bog'lash. Va React'da buning standart vositasi — React Router.

Lekin bu yerda muhim savol bor: SPA (11.3: 2.10) bitta index.html fayldan iborat — server faqat bitta sahifa beradi. Unda /products, /cart kabi turli "sahifalar" qanday paydo bo'ladi? Javob — client-side routing: React Router URL'ni brauzerda (server'ga bormasdan) kuzatadi va URL'ga mos komponentni ko'rsatadi. Foydalanuvchi uchun bu xuddi alohida sahifalardek tuyuladi (URL o'zgaradi, kontent almashadi), lekin aslida sahifa qayta yuklanmaydi — faqat React boshqa komponentni render qiladi. Bu — SPA'ni tez va silliq qiladi (oq miltillash yo'q), lekin uni to'g'ri sozlash o'z qoidalariga ega.

Bu bob: nega routing SPA'da (URL UI sinxronlash), client-side vs server routing (farq, brauzer History API), React Router setup (BrowserRouter / createBrowserRouter), Routes/Route (path element), Link/NavLink (navigatsiya, faol holat), dinamik segment va useParams (/user/:id), nested routes va Outlet (umumiy layout), index route va catch-all (404), useNavigate (dasturiy navigatsiya — login'dan keyin), useSearchParams (query string — filtr/sahifalash), useLocation, protected routes (auth guard), lazy routes (11.8 bilan), va data router (loader/action — React Router 6.4+), hamda React Router v6/v7 konteksti. Bu mavzu to'liq, zamonaviy (v6/v7) va amaliy holatda ochiladi.

O'xshatish: Routing — bu mehmonxonaning qabulxonasi va xona raqamlari. Sayt — bu mehmonxona, URL — xona raqami (/products — 305-xona). Code splitting'siz ilova — bu mehmon har safar boshqa xonaga o'tganda butun mehmonxonadan chiqib, qayta kirib, qabulxonadan yangi kalit oladigan tizim (sahifa qayta yuklanadi — sekin, oq ekran). Client-side routing — bu ichki liftlar va koridorlar: mehmon mehmonxonadan chiqmacdan (sahifa qayta yuklanmacdan) bir xonadan boshqasiga ichki yo'l bilan o'tadi (tez, silliq). React Router — bu qavat sxemasi va yo'l ko'rsatkichlari: qaysi raqam (URL) qaysi xonaga (komponent) olib borishini biladi, <Link> — koridordagi eshik (bossa o'sha xonaga), <Outlet> — har qavatda umumiy joy (lift, koridor — layout) bo'lib, faqat xona ichi almashadi.

Nega muhim?

  • Ko'p sahifali ilova asosi — har real SPA routing'ga tayanadi (yo'q ilova — bitta ekran).
  • URL — holat — URL ulashiladi, saqlanadi, "orqaga" ishlaydi (foydalanuvchi kutadi).
  • Layout va himoya — nested routes (umumiy layout) va protected routes (auth) — har ilovada.
  • Code splitting bilan — route-based splitting 11.8-bob routing ustiga quriladi — tez ilova.

2. Nazariya — chuqur tushuntirish

2.1. Nega routing — URL va UI'ni bog'lash

text
  ROUTING — URL'ni (manzil) UI bilan (qaysi komponent) BOG'LASH:

  URL                        KO'RINADIGAN KOMPONENT
  /                          <Home />
  /products                  <ProductList />
  /products/42               <ProductDetail id={42} />
  /cart                      <Cart />
  /profile                   <Profile />

  NEGA KERAK (URL — holat sifatida):
   Ulashish — foydalanuvchi URL'ni do'stiga yuboradi  o'sha sahifa ochiladi
   Bookmark — sahifani saqlash (favoritlar)
   Orqaga/oldinga — brauzer tugmalari ishlaydi (tarix)
   Yangilash — sahifani yangilaganda o'sha joyda qoladi
   SEO — har sahifaning o'z URL'i (qidiruv tizimi indekslaydi — 13.8)

   URL'siz SPA: hamma narsa bitta manzilda  ulashib/saqlab/orqaga qilib bo'lmaydi (yomon)
   Routing — URL'ni ilovaning HOLATI qiladi (bashoratli, ulashiladigan)

Routing — URL'ni (manzilni) UI bilan (qaysi komponent ko'rinishi) bog'lash. Har URL bir komponentga mos keladi: / <Home />, /products <ProductList />, /products/42 <ProductDetail />, /cart <Cart />. Nega kerak — chunki URL aslida ilovaning holati (state) sifatida ishlaydi: (1) ulashish — foydalanuvchi URL'ni do'stiga yuborsa, o'sha aniq sahifa ochiladi; (2) bookmark — sahifani saqlash; (3) orqaga/oldinga — brauzer tugmalari va tarix ishlaydi; (4) yangilash — sahifani yangilaganda foydalanuvchi o'sha joyda qoladi; (5) SEO — har sahifaning o'z URL'i bo'lsa, qidiruv tizimi uni indekslaydi 13.8-bob. Routing'siz SPA'da hamma narsa bitta URL'da bo'lardi — ulashib, saqlab, "orqaga" qilib bo'lmas edi (yomon tajriba). Routing URL'ni ilovaning bashoratli, ulashiladigan holatiga aylantiradi — bu zamonaviy web'ning asosiy kutilmasi. React Router bu bog'lanishni boshqaradi.

2.2. Client-side vs server routing

text
  SERVER ROUTING (an'anaviy — har URL = server'dan YANGI sahifa):
  /products bosildi  brauzer server'ga so'rov  server YANGI HTML qaytaradi  sahifa qayta yuklanadi
   har o'tishda: oq ekran, to'liq yuklanish (sekin, lekin SEO oson)

  CLIENT-SIDE ROUTING (SPA — React Router — sahifa qayta yuklanMAYDI):
  /products bosildi  React Router URL'ni o'zgartiradi (History API)  o'sha komponentni render
   server'ga bormaydi, oq ekran yo'q, DARROV almashadi (tez, silliq)

  ┌──────────────────────────────────────────────────────────────┐
  │ Server: har URL  server so'rovi  yangi HTML (qayta yuklanish) │
  │ Client: URL o'zgaradi  React komponent almashtiradi (yuklanish  │
  │         yo'q) — brauzer History API orqali                     │
  └──────────────────────────────────────────────────────────────┘

  BRAUZER HISTORY API (client routing'ning poydevori):
  - history.pushState() — URL'ni O'ZGARTIRADI (sahifa yuklamacdan)
  - popstate hodisasi — orqaga/oldinga tugmalari (React Router tinglaydi)

   Client routing tez (oq ekran yo'q), lekin SEO qiyin (bo'sh HTML  Next.js SSR — 13.3)
   React Router — History API ustiga qurilgan (URL'ni kuzatadi, komponent almashtiradi)

Client-side vs server routing — ikki xil yondashuv. Server routing (an'anaviy): har URL bosilganda brauzer server'ga so'rov yuboradi, server yangi HTML qaytaradi, sahifa to'liq qayta yuklanadi — har o'tishda oq ekran, to'liq yuklanish (sekin, lekin SEO oson — server tayyor HTML beradi). Client-side routing (SPA, React Router): URL bosilganda React Router URL'ni brauzerda o'zgartiradi (History API orqali) va o'sha URL'ga mos komponentni render qiladi — server'ga bormaydi, sahifa qayta yuklanmaydi, kontent darrov almashadi (tez, silliq, oq ekran yo'q). Buning poydevori — brauzerning History API'si: history.pushState() URL'ni sahifani yuklamasdan o'zgartiradi, popstate hodisasi orqaga/oldinga tugmalapini aniqlaydi (React Router bularni tinglaydi). Ikki tomon: (1) client routing tez (oq ekran yo'q, ilovaga o'xshash tajriba); (2) lekin SEO qiyinroq (qidiruv tizimi dastlab bo'sh HTML ko'radi — JavaScript ishlashini kutadi) — bu muammoni Next.js'ning SSR'i hal qiladi 13.3-bob. React Router — History API ustidagi qulay qatlam.

2.3. React Router setup — o'rnatish va ulanish

text
  O'RNATISH:
  npm install react-router-dom        # React Router (web uchun)

  IKKI USUL (React Router v6.4+):

  1. ESKI / ODDIY — <BrowserRouter> + JSX <Routes> (oddiy ilovalar uchun):
  // main.jsx
  import { BrowserRouter } from "react-router-dom";
  createRoot(...).render(
    <BrowserRouter>          {/* butun ilovani o'raydi (History API ulaydi) */}
      <App />
    </BrowserRouter>
  );

  2. YANGI / DATA ROUTER — createBrowserRouter (loader/action — 2.13, tavsiya):
  const router = createBrowserRouter([
    { path: "/", element: <Home /> },
    { path: "/products", element: <ProductList />, loader: productsLoader },
  ]);
  <RouterProvider router={router} />

  ┌──────────────────────────────────────────────────────────┐
  │ BrowserRouter + <Routes>: oddiy, JSX'da (kichik ilova)     │
  │ createBrowserRouter: data API (loader/action — katta — 2.13)│
  └──────────────────────────────────────────────────────────┘

   BrowserRouter (yoki RouterProvider) butun ilovani o'raydi (eng tepada — main.jsx)
   Bu bobda asosan JSX <Routes> sintaksisi (tushunarli); data router 2.13'da

React Router setupnpm install react-router-dom bilan o'rnatiladi (web uchun -dom). Ulashning ikki usuli bor (v6.4+). (1) Oddiy<BrowserRouter> butun ilovani o'raydi (main.jsx'da, eng tepada — u brauzer History API'siga ulaydi va URL kontekstini beradi), ichida JSX <Routes> bilan route'lar e'lon qilinadi. (2) Data RoutercreateBrowserRouter([...]) bilan route'lar massiv sifatida e'lon qilinadi va <RouterProvider router={router} /> bilan ulanadi; bu usul loader/action (ma'lumotni route darajasida yuklash — 2.13) imkonini beradi va katta ilovalar uchun tavsiya etiladi. Ikki nuqta: (1) BrowserRouter yoki RouterProvider — ilovaning eng tepasida (boshqa hamma route komponentlari uning ichida bo'lishi shart, aks holda "useNavigate may be used only in the context of a Router" xatosi); (2) bu bobda asosan tushunarli JSX <Routes> sintaksisini ishlatamiz (o'rganish oson), data router'ni 2.13'da ko'ramiz. Setup — routing'ning birinchi va majburiy qadami.

2.4. Routes va Route — path va element

text
  <Routes> va <Route> — URL'ni komponentga bog'laydi:

  <Routes>                                       {/* faqat BITTA mos Route'ni ko'rsatadi */}
    <Route path="/" element={<Home />} />
    <Route path="/about" element={<About />} />
    <Route path="/products" element={<ProductList />} />
    <Route path="/contact" element={<Contact />} />
  </Routes>

  - <Routes> — barcha Route'larni ko'rib, joriy URL'ga ENG MOS kelganini tanlaydi
  - <Route path="..." element={<Komponent />} /> — bitta yo'l  komponent
  - path: "/" (bosh), "/about" (statik), "/user/:id" (dinamik — 2.6)
  - element: ko'rsatiladigan JSX (komponent)

  ┌──────────────────────────────────────────────────────────┐
  │ URL: /products    <Routes> mos Route'ni topadi    render  │
  │ Faqat BITTA Route ko'rinadi (URL'ga eng mos kelgani)        │
  └──────────────────────────────────────────────────────────┘

   <Routes> — switch kabi: faqat bitta (eng mos) Route'ni render qiladi
   element={<Komponent />} (JSX) — element={Komponent} (havola) EMAS

Routes va Route — routing'ning yuragi. <Route path="..." element={<Komponent />} /> — bitta URL yo'lini bitta komponentga bog'laydi: path (URL — /, /about, yoki dinamik /user/:id — 2.6), element (ko'rsatiladigan JSX). <Routes> — barcha <Route>larni o'rab oladi va joriy URL'ga eng mos kelganini tanlab render qiladi (xuddi switch kabi — faqat bitta Route ko'rinadi). Masalan URL /products bo'lsa, <Routes> path="/products" li Route'ni topadi va uning elementini (<ProductList />) ko'rsatadi. Ikki muhim nuqta: (1) <Routes> faqat bitta (eng mos) Route'ni render qiladi — bu sahifalar bir-birini almashtirishini ta'minlaydi; (2) element ga JSX beriladi (element={<Komponent />} — qavs bilan), funksiya havolasi (element={Komponent}) emas — bu keng xato. v6'da path moslashtirish aqlli (eng aniq mos kelgani tanlanadi, tartibdan qat'i nazar) — bu eski versiyalardan farq. Routes/Route — barcha routing strukturasining asosiy qurilish bloki.

text
  <Link> — sahifa qayta yuklamay navigatsiya (oddiy <a> EMAS!):
  <Link to="/products">Mahsulotlar</Link>
  //  <a href="/products"> — sahifani QAYTA YUKLAYDI (SPA buziladi — 2.2)
  //  <Link to="..."> — client-side (History API — qayta yuklamaydi)

  <NavLink> — Link + FAOL holatni biladi (joriy sahifa menyuda ajralib tursin):
  <NavLink
    to="/products"
    className={({ isActive }) => isActive ? "active" : ""}   // faol bo'lsa "active" klass
  >
    Mahsulotlar
  </NavLink>
  //  /products'da bo'lsak, bu havola "active" klass oladi (CSS bilan ajratamiz)

  ┌──────────────────────────────────────────────────────────┐
  │ <a href>: sahifa qayta yuklanadi (SPA buziladi) — ISHLATMA │
  │ <Link to>: client navigatsiya | <NavLink>: + faol holat   │
  └──────────────────────────────────────────────────────────┘

   Ilova ICHIDA — har doim <Link>/<NavLink> (oddiy <a> faqat TASHQI saytlarga)
   NavLink — navbar/menyu uchun (joriy sahifani ko'rsatish — UX)

Link va NavLink — client-side navigatsiya komponentlari. <Link to="/products"> — sahifani qayta yuklamasdan navigatsiya qiladi (History API orqali — 2.2). Bu juda muhim: oddiy <a href="/products"> ishlatilsa, brauzer sahifani to'liq qayta yuklaydi (server'ga so'rov, oq ekran — SPA'ning butun afzalligi yo'qoladi); shuning uchun ilova ichida har doim <Link> ishlatiladi (oddiy <a> faqat tashqi saytlarga — Google, ijtimoiy tarmoq). <NavLink>Linkning kuchaytirilgan versiyasi: u joriy sahifa faol ekanini biladi va className/styleni funksiya orqali beradi (({ isActive }) => isActive ? "active" : "") — shuning uchun joriy sahifa menyuda ajralib turadi (masalan ko'k rangda). Ikki amaliy nuqta: (1) ilova ichidagi har navigatsiya <Link>/<NavLink> bilan (oddiy <a> SPA'ni buzadi); (2) NavLink navbar/menyu uchun ideal (foydalanuvchi qayerda ekanini ko'radi — yaxshi UX). Bularsiz client-side routing ishlamaydi.

2.6. Dinamik segment va useParams (/user/:id)

text
  DINAMIK SEGMENT — URL'ning O'ZGARUVCHAN qismi (`:` bilan — masalan id):

  <Route path="/products/:id" element={<ProductDetail />} />
  //                    └─ dinamik (har qanday qiymat: /products/42, /products/abc)

  KOMPONENTDA — useParams() bilan o'qiymiz:
  function ProductDetail() {
    const { id } = useParams();        // URL'dan id (string — "42")
    // bu id bilan ma'lumot olamiz (11.7 useFetch yoki 12.4):
    const { data } = useFetch(`/api/products/${id}`);
    return <h1>{data?.name}</h1>;
  }

  KO'P SEGMENT:
  <Route path="/users/:userId/posts/:postId" element={<Post />} />
  const { userId, postId } = useParams();   // ikkalasi ham

  ┌──────────────────────────────────────────────────────────┐
  │ /products/:id    /products/42    useParams().id === "42" │
  │ Bitta Route  cheksiz sahifa (har id — boshqa mahsulot)    │
  └──────────────────────────────────────────────────────────┘

   useParams qiymatlari — har doim STRING (raqam kerak bo'lsa Number(id))
   Dinamik segment — bitta Route bilan ko'p sahifa (mahsulot, profil, post...)

Dinamik segment va useParams — URL'ning o'zgaruvchan qismini boshqaradi. path="/products/:id" da :iddinamik segment (: bilan belgilanadi): u har qanday qiymatga mos keladi (/products/42, /products/123). Komponentda bu qiymatni useParams() hook'i bilan o'qiysiz: const { id } = useParams() — URL'dan id ni oladi (masalan "42"), keyin u bilan ma'lumot olasiz (useFetch(\/api/products/${id}`)— 11.7, 12.4). Bir nechta dinamik segment ham bo'lishi mumkin:path="/users/:userId/posts/:postId"const { userId, postId } = useParams(). Ikki muhim nuqta: (1) useParamsqaytaradigan qiymatlar **har doim string** (URL — matn), shuning uchun raqam kerak bo'lsaNumber(id)bilan o'giriladi; (2) eng katta foyda — bitta Route bilan **cheksiz** sahifa:/products/:idbitta route, lekin harid` boshqa mahsulot sahifasini ko'rsatadi (har mahsulotga alohida Route yozish shart emas). Bu — mahsulot tafsiloti, foydalanuvchi profili, blog post kabi har dinamik kontent sahifasinning standart naqshi.

2.7. Nested routes va Outlet — umumiy layout

text
  MUAMMO: ko'p sahifada UMUMIY qism bor (navbar, sidebar, footer) — takrorlama!

  YECHIM — NESTED ROUTES (ichma-ich) + <Outlet> (bola route shu yerda render bo'ladi):

  <Routes>
    <Route path="/" element={<Layout />}>        {/* ota — umumiy qobiq */}
      <Route index element={<Home />} />          {/* /  Home (index — 2.8) */}
      <Route path="products" element={<Products />} />   {/* /products */}
      <Route path="about" element={<About />} />          {/* /about */}
    </Route>
  </Routes>

  // Layout — umumiy qism + <Outlet> (bola route O'RNI):
  function Layout() {
    return (
      <div>
        <Navbar />                {/* har sahifada */}
        <main>
          <Outlet />              {/*  bu yerda bola route (Home/Products/About) render bo'ladi */}
        </main>
        <Footer />                {/* har sahifada */}
      </div>
    );
  }

  ┌──────────────────────────────────────────────────────────┐
  │ Layout (Navbar + Outlet + Footer) — o'zgarmaydi            │
  │ <Outlet> ichi — URL'ga qarab almashadi (Home/Products...)  │
  └──────────────────────────────────────────────────────────┘

   Outlet — "bola route bu yerda ko'rinadi" (layout'ning o'zgaruvchan qismi)
   Nested routes — takrorni yo'qotadi (navbar/footer bir marta — Layout'da)

Nested routes va Outlet — umumiy layout muammosini hal qiladi. Muammo: ko'p sahifada bir xil qism bor (navbar, sidebar, footer) — har sahifaga takrorlash zerikarli va mo'rt. Yechimnested (ichma-ich) routes: ota Route umumiy layoutni (qobiq) beradi, bola Route'lar uning ichidagi o'zgaruvchan qismni. Layout komponentida <Outlet /> qo'yasiz — bu "bola route shu yerda render bo'ladi" degan joy belgisi. Masalan <Route path="/" element={<Layout />}> ichida <Route path="products" element={<Products />} /> — URL /products bo'lsa, Layout (Navbar + Outlet + Footer) render bo'ladi va <Outlet> o'rniga <Products /> qo'yiladi. Foydalanuvchi sahifalar orasida o'tganda faqat <Outlet> ichi almashadi, Navbar/Footer o'zgarmaydi (qayta render bo'lmaydi). Ikki foyda: (1) takror yo'qoladi — navbar/footer bir marta Layout'da yoziladi; (2) chuqurroq nesting mumkin (masalan /dashboard ichida /dashboard/settings, /dashboard/analytics — har biri o'z Outlet'i bilan — murakkab ilova strukturasi). Nested routes — har jiddiy ilovaning routing arxitekturasining asosi.

2.8. Index route va catch-all (404)

text
  INDEX ROUTE — ota yo'lining O'ZI ochilganda ko'rinadigan bola (default):
  <Route path="/" element={<Layout />}>
    <Route index element={<Home />} />        {/* /  Home (path'siz, "index") */}
    <Route path="products" element={<Products />} />
  </Route>
  // /   Layout + Home (index)
  // /products  Layout + Products

  CATCH-ALL (404) — hech bir route mos kelmasa (* — "qolgan hammasi"):
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/products" element={<Products />} />
    <Route path="*" element={<NotFound />} />   {/*  hech qaysiga mos kelmasa — 404 */}
  </Routes>

  ┌──────────────────────────────────────────────────────────┐
  │ index: ota yo'lining default bolasi (/  Home)             │
  │ path="*": mos kelmagan har URL (404 sahifa) — ENG OXIRDA   │
  └──────────────────────────────────────────────────────────┘

   index — path o'rniga (ota yo'lining "uy" sahifasi)
   "*" 404 uchun — noto'g'ri URL'da foydalanuvchi yo'qolmasin (UX)

Index route va catch-all — routing'ning ikki muhim qismi. Index route — ota yo'lining o'zi ochilganda ko'rinadigan default bola: <Route index element={<Home />} /> (path o'rniga index). Masalan <Route path="/" element={<Layout />}> ichida <Route index element={<Home />} /> bo'lsa, URL aynan / bo'lganda Layout + Home ko'rinadi (ota yo'lining "uy" sahifasi). Index route'siz, / ochilganda faqat Layout ko'rinardi (Outlet bo'sh). Catch-all (404) — hech bir route mos kelmaganda ko'rinadigan route: <Route path="*" element={<NotFound />} /> (* — "qolgan barcha URL'lar"). Foydalanuvchi noto'g'ri yoki mavjud bo'lmagan manzilga kirsa (/xyz), NotFound sahifasi ko'rsatiladi. Ikki nuqta: (1) index — ota route'ning default kontenti (har layout'da bo'lishi tavsiya); (2) path="*" — 404 uchun, va u eng oxirda turishi mantiqli (eng kam aniq mos). Catch-all'siz, noto'g'ri URL'da bo'sh ekran ko'rinardi — foydalanuvchini yo'qotmaslik uchun chiroyli 404 sahifa (orqaga havola bilan) muhim UX detali.

2.9. useNavigate — dasturiy navigatsiya

text
  useNavigate — KODDAN (bosish emas) navigatsiya qilish (hodisa/effekt natijasida):

  function LoginForm() {
    const navigate = useNavigate();
    async function handleSubmit(e) {
      e.preventDefault();
      await api.login(...);
      navigate("/dashboard");        //  login MUVAFFAQIYATLI  dashboard'ga o'tkaz
    }
  }

  USULLAR:
  navigate("/products")              // o'sha sahifaga
  navigate("/products", { replace: true })   // tarixni ALMASHTIR (orqaga bossa login'ga qaytmasin)
  navigate(-1)                       // ORQAGA (bitta qadam — brauzer "orqaga" kabi)
  navigate(1)                        // oldinga
  navigate("/cart", { state: { from: "product" } })   // qo'shimcha ma'lumot uzatish 2.11-bob

  QACHON useNavigate (Link emas):
   Hodisa natijasida (login/forma yuborilgach  boshqa sahifaga)
   Shart bajarilgach (ruxsat yo'q  login'ga, vaqt tugadi  bosh sahifaga)
   Taymer/effekt (3s'dan keyin yo'naltirish)

   Foydalanuvchi BOSADIGAN navigatsiya  <Link>; KOD qiladigan  useNavigate
   replace: true — almashtiradi (forma/login'dan keyin — orqaga qaytarmasin)

useNavigate — koddan (foydalanuvchi bosishidan emas) navigatsiya qilish hook'i. const navigate = useNavigate() — keyin navigate("/dashboard") bilan boshqa sahifaga o'tasiz. Bu hodisa yoki shart natijasida ishlatiladi: masalan login muvaffaqiyatli bo'lgach (await api.login(); navigate("/dashboard")), ruxsat yo'q bo'lsa (navigate("/login")), yoki taymer tugagach. Usullar: navigate("/products") (o'sha sahifaga), navigate("/products", { replace: true }) (tarixda almashtiradi — masalan login'dan keyin, foydalanuvchi "orqaga" bossa login'ga qaytmasin), navigate(-1) (orqaga, brauzer "orqaga" tugmacidek), navigate("/cart", { state: {...} }) (qo'shimcha ma'lumot bilan — 2.11). Asosiy farq: foydalanuvchi bosadigan navigatsiya <Link> (deklarativ, a11y); kod qiladigan (hodisa/shart natijasida) useNavigate (imperativ). replace: true muhim naqsh — forma/login/qadamli jarayondan keyin foydalanuvchini orqaga qaytarmaslik uchun (tarixni almashtiradi). useNavigate — interaktiv oqimlar (auth, wizard, checkout)ning standart vositasi.

2.10. useSearchParams — query string (filtr, sahifalash)

text
  QUERY STRING — URL'ning "?" dan keyingi qismi (filtr/saralash/sahifa holati):
  /products?category=phones&sort=price&page=2
  //         └────────────── query params ──────────┘

  useSearchParams — query'ni O'QISH va YOZISH (URL'da state saqlash):
  const [searchParams, setSearchParams] = useSearchParams();

  // O'QISH:
  const category = searchParams.get("category");   // "phones"
  const page = Number(searchParams.get("page")) || 1;

  // YOZISH (URL'ni yangilaydi — sahifa qayta yuklanmaydi):
  setSearchParams({ category: "laptops", page: "1" });   // /products?category=laptops&page=1

  NEGA query (state emas, URL'da):
   Ulashiladigan (filtrlangan natija URL'i — do'stga yuborish)
   Orqaga/yangilash ishlaydi (filtr saqlanadi)
   Bookmark qilinadigan

  ┌──────────────────────────────────────────────────────────┐
  │ Filtr/saralash/sahifa holati  query params (URL'da)       │
  │  ulashiladigan, saqlanadigan (useState'dan afzal bu yerda)│
  └──────────────────────────────────────────────────────────┘

   Filtr/sahifani query'da saqla (useState emas) — ulashib/saqlab bo'ladi
   searchParams qiymatlari — string (raqam kerak bo'lsa Number)

useSearchParams — URL'ning query string qismini (? dan keyin — ?category=phones&page=2) o'qish va yozish hook'i. const [searchParams, setSearchParams] = useSearchParams()useState ga o'xshaydi, lekin holat URL'da saqlanadi. O'qish: searchParams.get("category") ("phones"), Number(searchParams.get("page")). Yozish: setSearchParams({ category: "laptops", page: "1" }) — URL'ni yangilaydi (/products?category=laptops&page=1), sahifani qayta yuklamaydi. Nega query string (oddiy useState emas): filtr, saralash, sahifalash (pagination) holatini URL'da saqlash — (1) ulashiladigan (foydalanuvchi filtrlangan natija URL'ini do'stiga yuboradi o'sha aniq holat ochiladi); (2) orqaga/yangilash ishlaydi (filtr yo'qolmaydi); (3) bookmark qilinadi. Ikki nuqta: (1) filtr/saralash/sahifalash holatini useState emas, query paramsda saqla (ulashib/saqlab bo'ladi — bu yaxshi UX); (2) qiymatlar string (raqam kerak bo'lsa Number). Bu — mahsulot ro'yxati, qidiruv natijalari, jadval kabi filtrlanadigan sahifalarda hal qiluvchi naqsh.

2.11. useLocation va navigation state

text
  useLocation — joriy URL haqida MA'LUMOT (qaysi manzildamiz):
  const location = useLocation();
  location.pathname   // "/products"  (yo'l)
  location.search     // "?sort=price" (query)
  location.hash       // "#section"
  location.state      // navigate'dan uzatilgan qo'shimcha ma'lumot 2.9-bob

  NAVIGATION STATE — sahifalar orasida ma'lumot uzatish (URL'da KO'RINMAY):
  // Yuborish:
  navigate("/checkout", { state: { product: selectedProduct } });
  // Olish (yangi sahifada):
  const location = useLocation();
  const product = location.state?.product;

  TIPIK ishlatish:
  - "qayerdan keldi" (login'dan keyin oldingi sahifaga qaytarish):
    navigate("/login", { state: { from: location.pathname } });
  - modal/scroll holati; o'tishda vaqtincha ma'lumot

   location.state — URL'da ko'rinmaydi (yangilaganda YO'QOLADI — vaqtincha ma'lumot uchun)
   Muhim/saqlanishi kerak ma'lumot — query 2.10-bob yoki state management (12), location.state emas

useLocation va navigation state — joriy URL haqida ma'lumot va sahifalar orasida ma'lumot uzatish. useLocation() joriy URL obyektini qaytaradi: pathname (yo'l — /products), search (query — ?sort=price), hash, va state (navigate'dan uzatilgan ma'lumot). Navigation state — sahifalar orasida URL'da ko'rinmaydigan ma'lumot uzatish: yuborishda navigate("/checkout", { state: { product } }), olishda const { product } = useLocation().state ?? {}. Tipik ishlatish: (1) "qayerdan keldi" — himoyalangan sahifaga kirmoqchi bo'lgan foydalanuvchini login'ga yuborib, login'dan keyin oldingi sahifaga qaytarish (navigate("/login", { state: { from: location.pathname } }) — 2.12); (2) o'tishda vaqtincha ma'lumot (tanlangan element, scroll holati). Ikki muhim nuqta: (1) location.state URL'da ko'rinmaydi va sahifani yangilaganda yo'qoladi (chunki u tarix yozuvida, URL'da emas) — shuning uchun faqat vaqtincha ma'lumot uchun; (2) saqlanishi/ulashilishi kerak ma'lumot — query 2.10-bob yoki state management (12-QISM)da saqlanishi kerak, location.stateda emas. useLocation — routing oqimida kontekstni bilish vositasi.

2.12. Protected routes — auth guard

text
  PROTECTED ROUTE — faqat AUTENTIFIKATSIYADAN o'tgan foydalanuvchi kira oladi:

  function ProtectedRoute({ children }) {
    const { user } = useAuth();                  // 11.7 — Context'dan user
    const location = useLocation();
    if (!user) {
      //  kirmagan  login'ga (va "qayerga bormoqchi edi"ni sakla — 2.11)
      return <Navigate to="/login" state={{ from: location.pathname }} replace />;
    }
    return children;                             // kirgan  sahifani ko'rsat
  }

  ISHLATISH (himoyalangan route'ni o'rash):
  <Route path="/dashboard" element={
    <ProtectedRoute><Dashboard /></ProtectedRoute>
  } />

  // YOKI nested layout sifatida (barcha bola route himoyalangan):
  <Route element={<ProtectedRoute><Layout/></ProtectedRoute>}>
    <Route path="/dashboard" element={<Dashboard />} />
    <Route path="/settings" element={<Settings />} />
  </Route>

  ┌──────────────────────────────────────────────────────────┐
  │ kirgan  sahifa; kirmagan  <Navigate to="/login" replace> │
  │ <Navigate> — deklarativ yo'naltirish (komponent kabi)       │
  └──────────────────────────────────────────────────────────┘

   <Navigate> — render paytida yo'naltiradi (useNavigate — hodisada; Navigate — JSX'da)
   Frontend guard — UX uchun; HAQIQIY himoya BACKEND'da (token tekshirish — 5.16, 14)

Protected routes (auth guard) — faqat autentifikatsiyadan o'tgan foydalanuvchi kira oladigan sahifalar. Buning uchun ProtectedRoute o'rovchi komponent yaratiladi: u useAuth() 11.7-bob orqali userni tekshiradi — agar user yo'q bo'lsa, <Navigate to="/login" replace /> bilan login'ga yo'naltiradi (va state={{ from: location.pathname }} bilan "qayerga bormoqchi edi"ni saqlaydi — login'dan keyin qaytarish uchun — 2.11); user bor bo'lsa, childrenni (himoyalangan sahifa) ko'rsatadi. Ishlatish: himoyalangan route'ni o'rab (<ProtectedRoute><Dashboard /></ProtectedRoute>), yoki nested layout sifatida (bir guruh route'ni birata himoyalash — <Route element={<ProtectedRoute><Layout/></ProtectedRoute>}> ichida bola route'lar). <Navigate> — deklarativ yo'naltirish komponenti (render paytida ishlaydi — useNavigate hodisada ishlatilsa, Navigate JSX'da). Eng muhim ogohlantirish: frontend guard faqat UX uchun (foydalanuvchini to'g'ri sahifaga yo'naltirish) — haqiqiy xavfsizlik backend'da (har API so'rovda token tekshirish — 5.16, 14-QISM); frontend kodni har kim ko'ra/o'zgartira oladi, shuning uchun himoyaga faqat unga tayanma. Protected routes — har auth'li ilovaning standart qismi.

2.13. Lazy routes va data router (loader/action)

text
  LAZY ROUTES (11.8 bilan) — har sahifani alohida chunk:
  const Dashboard = lazy(() => import("./pages/Dashboard"));
  <Route path="/dashboard" element={
    <Suspense fallback={<PageLoader/>}><Dashboard/></Suspense>
  } />

  DATA ROUTER (createBrowserRouter — 2.3) — LOADER/ACTION (ma'lumot route darajasida):
  const router = createBrowserRouter([
    {
      path: "/products/:id",
      element: <ProductDetail />,
      loader: async ({ params }) => {            //  sahifa RENDER'dan OLDIN ma'lumot yuklaydi
        return fetch(`/api/products/${params.id}`).then(r => r.json());
      },
    },
  ]);
  // Komponentda:
  function ProductDetail() {
    const product = useLoaderData();             // loader qaytargan ma'lumot (tayyor!)
    return <h1>{product.name}</h1>;
  }

  LOADER afzalligi (useEffect+fetch'dan):
   Ma'lumot render'dan OLDIN yuklanadi ("render-as-you-fetch" — tez)
   Loading/waterfall muammosi kamayadi; URL bilan birga ma'lumot
   action — forma yuborish (POST) route darajasida

   Data router (loader/action) — React Router 6.4+ (Remix'dan); katta ilovada tavsiya
   Lekin amalda ko'p loyiha TanStack Query 12.4-bob ishlatadi (kesh/sync kuchli)

Lazy routes va data router — routing'ning ikki ilg'or imkoniyati. Lazy routes (11.8 bilan): har sahifani lazy(() => import()) + <Suspense> bilan alohida chunk qilasiz — bu route-based code splitting (eng keng amaliyot). Data router (createBrowserRouter — 2.3): route darajasida loader (ma'lumot yuklash) va action (forma yuborish) e'lon qilinadi. loader — sahifa render bo'lishdan oldin ma'lumotni yuklaydi (loader: async ({ params }) => fetch(...)), komponent esa uni useLoaderData() bilan tayyor holda oladi. Loader afzalligi (useEffect+fetch'dan — 11.5): ma'lumot render'dan oldin yuklanadi ("render-as-you-fetch" — tezroq, "loading waterfall" kamayadi), URL bilan birga ma'lumot keladi; action esa forma yuborishni (POST/PUT) route darajasida boshqaradi. Ikki nuqta: (1) data router (loader/action) — React Router 6.4+ da paydo bo'ldi (Remix'dan olingan g'oya) va katta ilovalar uchun tavsiya etiladi; (2) lekin amalda ko'p loyiha ma'lumot olish uchun TanStack Query 12.4-bob ishlatadi (kesh, sinxronlash, retry kuchliroq) — ikkalasini birga ham ishlatish mumkin. Bu bobda asosan element-based routing'ni o'rgandik; loader/action — keyingi qadam (12.4, 13.5 bilan bog'liq).

2.14. React Router v6/v7 va arxitektura

text
  REACT ROUTER VERSIYALARI (2026):
  - v6 — keng tarqalgan (createBrowserRouter, data API, hooks)
  - v7 — eng yangi (Remix bilan birlashdi); v6 bilan deyarli mos, framework rejimi ham bor
   bu bobdagi hammasi v6 va v7'da ishlaydi (asosiy API barqaror)

  ROUTING ARXITEKTURASI (toza ilova):
  src/
  ├── pages/           sahifa komponentlari (Home, Products, Profile — 11.3: 2.9)
  ├── routes/          route ta'riflari (router config, protected routes)
  ├── components/      Layout, Navbar (Outlet bilan)
  └── App.jsx          <RouterProvider> yoki <Routes>

  ALTERNATIVALAR (kontekst):
  - TanStack Router — type-safe routing (TypeScript kuchli)
  - Next.js (13) — file-based routing (papka = route, avtomatik — 13.2)

  ┌──────────────────────────────────────────────────────────┐
  │ React Router — SPA (Vite) standarti                        │
  │ Next.js — file-based (papka strukturasi = route — 13.2)    │
  └──────────────────────────────────────────────────────────┘

   React Router v6/v7 — Vite/SPA uchun standart (bu bob)
   Next.js'da routing BOSHQACHA (file-based, avtomatik — 13-QISM)

React Router v6/v7 va arxitektura — versiyalar va tashkillash. Versiyalar (2026): v6 keng tarqalgan (createBrowserRouter, data API, hooks — bu bobdagi hammasi); v7 eng yangi (Remix framework bilan birlashdi, v6 bilan deyarli mos, qo'shimcha "framework rejimi" bor) — bu bobdagi barcha asosiy API ikkalasida ham barqaror ishlaydi. Routing arxitekturasi (toza ilova): pages/ (sahifa komponentlari — 11.3: 2.9), routes/ (route ta'riflari, protected routes), components/ (Layout, Navbar — Outlet bilan), App.jsx (<RouterProvider>/<Routes>). Alternativalar (kontekst): TanStack Router (type-safe routing — TypeScript bilan kuchli kafolatlar), va Next.js (13-QISM) — file-based routing (papka strukturasi = route, qo'lda route yozish kerak emas — 13.2). Ikki nuqta: (1) React Router v6/v7 — Vite/SPA ilovalari uchun standart (bu bob shunga bag'ishlangan); (2) Next.js'da routing butunlay boshqacha (file-based, avtomatik — 13-QISM) — lekin tushunchalar (dinamik segment, nested layout, navigatsiya) o'xshaydi. To'g'ri tanlov: oddiy SPA React Router; SSR/SEO kerak Next.js (13).

2.15. Router turlari — BrowserRouter, HashRouter, MemoryRouter

text
  UCH XIL ROUTER (URL'ni QAYERDA saqlaydi):

  BrowserRouter — TOZA URL (History API), tavsiya:
  /products/42            (chiroyli, SEO'ga mos)
   Server SPA fallback kerak (yangilaganda 404 bo'lmasin — Xato 2)

  HashRouter — URL'da "#" (hash qismi):
  /#/products/42          (# dan keyingi qism server'ga BORMAYDI)
   Server sozlash kerak EMAS (static hosting — GitHub Pages); lekin URL xunuk, SEO yomon

  MemoryRouter — URL'ni brauzerda EMAS, XOTIRADA saqlaydi:
  (manzil satri o'zgarmaydi) — test, Storybook, React Native uchun

  ┌──────────────────────────────────────────────────────────┐
  │ BrowserRouter: toza URL (standart) — server fallback kerak │
  │ HashRouter: /#/ (static hosting) | MemoryRouter: test/RN   │
  └──────────────────────────────────────────────────────────┘

   Deyarli har doim BrowserRouter (toza URL); HashRouter faqat server sozlab bo'lmaganda

Router turlari — React Router URL'ni qayerda saqlashiga qarab uch xil "router" beradi. BrowserRouter — brauzer History API'sidan foydalanadi, URL toza bo'ladi (/products/42), SEO'ga mos — bu standart tanlov (deyarli har ilovada). Uning yagona sharti: server barcha yo'llarni index.htmlga qaytarishi kerak (SPA fallback — aks holda /productsni yangilaganda 404 — Xato 2). HashRouter — URL'da # ishlatadi (/#/products/42); # dan keyingi qism brauzerda qoladi va server'ga yuborilmaydi, shuning uchun server sozlash shart emas — bu static hosting (GitHub Pages, oddiy fayl-server) uchun qulay, lekin URL xunuk va SEO yomonroq. MemoryRouter — URL'ni brauzer manzil satrida emas, xotirada saqlaydi (manzil ko'rinmaydi/o'zgarmaydi); bu test, Storybook va React Native (manzil satri yo'q muhitlar) uchun. Amaliy qoida: toza URL kerak BrowserRouter (deyarli har doim); server sozlab bo'lmasa HashRouter; test/izolyatsiya MemoryRouter.

2.16. Splat, optional segment va relative/absolute yo'l

text
  SPLAT (*) — "qolgan barcha yo'lni ushla" (catch-all yoki fayl yo'llar):
  <Route path="files/*" element={<Files />} />
  // /files/docs/2026/hisobot.pdf    useParams()["*"] === "docs/2026/hisobot.pdf"

  OPTIONAL SEGMENT (v6.4+, "?" bilan) — bor ham, yo'q ham bo'lishi mumkin:
  <Route path="/products/:id?" element={<Products />} />
  // /products VA /products/42 — ikkalasi ham mos

  RELATIVE vs ABSOLUTE yo'l (nested route ichida):
  <Link to="/products">    ABSOLUTE (har doim /products — ildizdan)
  <Link to="edit">         RELATIVE (joriy route'ga nisbatan — /users/42/edit)
  <Link to="..">           bir daraja YUQORI (parentga)
  navigate(".."), navigate("../settings")   // navigate ham relative

  ┌──────────────────────────────────────────────────────────┐
  │ "*": qolgan yo'l (catch-all/fayl) | ":id?": ixtiyoriy      │
  │ "/x": absolute | "x", "..": relative (joriy route'dan)     │
  └──────────────────────────────────────────────────────────┘

   Nested route ichida relative yo'l qulay (kod ko'chirsa ham to'g'ri qoladi)
   "/" bilan boshlanmagan yo'l — RELATIVE (joriy route bilan qo'shiladi)

Splat, optional segment va relative/absolute yo'l — path yozishning uch nozik jihati. Splat (*) — "qolgan barcha yo'lni ushla": path="files/*" /files/docs/2026/x.pdf kabi ixtiyoriy chuqurlikdagi yo'lga mos keladi, va ushlangan qism useParams()["*"] (yoki splat) orqali olinadi — bu fayl-brauzer yoki 404 catch-all (path="*") uchun ishlatiladi. Optional segment (:id?) — segment oxiridagi ? uni ixtiyoriy qiladi (v6.4+): path="/products/:id?" ham /products, ham /products/42 ga mos — bir Route ikki holatni qoplaydi. Relative vs absolute yo'lto/navigateda / bilan boshlangan yo'l absolute (har doim ildizdan — /products), / siz yo'l esa relative (joriy route'ga nisbatan qo'shiladi — to="edit" /users/42 ichida /users/42/edit bo'ladi), to=".." esa bir daraja yuqoriga (parentga) chiqadi. Ikki nuqta: (1) nested route ichida relative yo'l qulay — komponentni boshqa joyga ko'chirsangiz ham havolalar to'g'ri qoladi; (2) / siz yozilgan yo'l relative ekanini yodda tuting (aks holda kutilmagan manzilga o'tib qolish mumkin).

2.17. Error handling — errorElement, useRouteError

text
  DATA ROUTER'da xato boshqaruvi (loader/action/render xatosini USHLASH):

  const router = createBrowserRouter([
    {
      path: "/products/:id",
      element: <ProductDetail />,
      loader: productLoader,           // xato tashlasa (throw) yoki 404 Response...
      errorElement: <RouteError />,    //  ...bu ko'rsatiladi (element o'rniga)
    },
  ]);

  function RouteError() {
    const error = useRouteError();     // ushlangan xato (yoki Response)
    if (error.status === 404) return <h1>Sahifa topilmadi</h1>;
    return <h1>Xatolik: {error.message}</h1>;
  }

  ┌──────────────────────────────────────────────────────────┐
  │ errorElement: route'dagi xatoni ushlaydi (loader/render)   │
  │ useRouteError(): ushlangan xatoni o'qish (status/message)  │
  └──────────────────────────────────────────────────────────┘

   errorElement — data router uchun Error Boundary 11.6-bob analogi (route darajasida)
   Eng tepadagi errorElement — butun ilova uchun "zaxira" xato sahifasi

Error handling (errorElement, useRouteError) — data router'da xatolarni boshqarish. Route obyektiga errorElement qo'shsangiz, o'sha route'ning loader/action'i xato tashlasa (throw) yoki render paytida xato bo'lsa, React Router element o'rniga errorElementni ko'rsatadi. Xato komponentida useRouteError() hook'i ushlangan xatoni beradi — u oddiy Error yoki Response bo'lishi mumkin (error.status === 404 bo'lsa "topilmadi" sahifasi, aks holda umumiy xato). Bu — 11.6'dagi Error Boundaryning route darajacidagi analogi: har route o'z xatosini alohida ushlashi, yoki eng tepadagi bitta errorElement butun ilova uchun zaxira xato sahifasi bo'lishi mumkin. Ikki nuqta: (1) loader'da throw new Response("...", { status: 404 }) bilan 404'ni "ma'lumot yo'q" holatida chiroyli boshqarasiz (Misol 13'da ko'rgan throw); (2) errorElementsiz, loader xatosi ilovani "sindiradi" (oq ekran) — shuning uchun data router'da u deyarli majburiy.

2.18. Navigation state va pending UI — useNavigation, defer/Await

text
  useNavigation — DATA ROUTER'da o'tish HOLATINI biladi (loader yuklanmoqda?):

  function GlobalSpinner() {
    const navigation = useNavigation();
    // navigation.state: "idle" | "loading" | "submitting"
    return navigation.state === "loading" ? <TopProgressBar /> : null;
  }
  //  sahifa loader'i yuklanayotganda global progress bar (silliq UX)

  defer + Await — SEKIN ma'lumotni KUTMAY sahifani ko'rsatish (streaming):
  loader: () => defer({ reviews: fetch(...).then(r => r.json()) });   // kutmaydi
  // Komponentda:
  const { reviews } = useLoaderData();
  <Suspense fallback={<Spinner/>}>
    <Await resolve={reviews}>{(data) => <Reviews items={data} />}</Await>
  </Suspense>

  ┌──────────────────────────────────────────────────────────┐
  │ useNavigation: o'tish holati (loading/submitting)  pending UI│
  │ defer/Await: sekin qismni kutmay ko'rsat (streaming — tez)  │
  └──────────────────────────────────────────────────────────┘

   useNavigation — data router loader'i uzoq bo'lganda "yuklanmoqda" ko'rsatish (UX)
   defer — muhim qismni darrov, sekin qismni (izohlar) keyin (kutish yo'q)

Navigation state va pending UI — data router' da o'tish tajribasini silliqlash. useNavigation() joriy navigatsiya holatini beradi: navigation.state "idle" (bo'sh), "loading" (loader ma'lumot yuklamoqda), yoki "submitting" (Form action bajarmoqda). Bu bilan pending UI yasaladi — masalan loader yuklanayotganda global progress bar yoki sahifani yarim shaffof qilish (foydalanuvchi "nimadir bo'lmoqda" deb biladi — silliq UX, oq ekran o'rniga). defer + <Await> — sekin ma'lumotni kutmay sahifani ko'rsatish (streaming): loaderda defer({ reviews: fetch(...) }) bilan sekin qismni (masalan izohlar) kutmasdan qaytarasiz, komponentda esa <Suspense><Await resolve={reviews}>...</Await></Suspense> bilan u tayyor bo'lganda o'rniga qo'yasiz. Natijada: muhim kontent (mahsulot nomi/narxi) darrov, sekin qismi (izohlar) keyin keladi — "loading waterfall"siz tez tajriba. Bular data router'ning ilg'or imkoniyatlari (React Router 6.4+): Form + action + useActionData bilan birga forma yuborishni ham route darajasida boshqaradi (server-formalar uslubi — Remix'dan). Amalda esa oddiy ilovada useNavigation/pending UI eng ko'p ishlatiladi; defer — og'ir sahifalarda.

2.19. Scroll restoration, useMatch va breadcrumb

text
  SCROLL RESTORATION — sahifa o'tishida scroll pozitsiyasi (SPA muammosi):
  // Muammo: /products (pastga scroll qilingan)  /cart  ORQAGA  scroll eski joyda EMAS
  // Data router — <ScrollRestoration /> (avtomatik: orqaga  eski scroll, yangi  tepaga)
  <ScrollRestoration />          // root layout'da bir marta

  useMatch — joriy URL berilgan naqshga MOS kelishini tekshirish (bool/obyekt):
  const match = useMatch("/products/:id");   // /products/42  obyekt; boshqa  null
  // masalan tab yoki breadcrumb "faol"ligini aniqlash uchun

  BREADCRUMB (non  mahsulot  tafsilot yo'lchisi) — nested route + handle:
  { path: "products", handle: { crumb: "Mahsulotlar" }, children: [...] }
  const matches = useMatches();   // joriy mos route'lar zanjiri  breadcrumb quramiz

   ScrollRestoration — SPA'da "orqaga bosganda scroll qayerda edi" muammosini hal qiladi
   useMatches + route.handle — breadcrumb (yo'lchi) qurishning toza usuli

Scroll restoration, useMatch va breadcrumb — routing UX'ining uch qo'shimcha detali. Scroll restoration — SPA'da klassik muammo: /productsda pastga scroll qilib, /cartga o'tib, "orqaga" bosganda foydalanuvchi scroll eski joyida bo'lishini kutadi (server saytlar buni avtomatik qiladi, SPA — yo'q). Data router'da root layout'ga bir marta <ScrollRestoration /> qo'yasiz — u avtomatik boshqaradi: "orqaga" bosilganda oldingi scroll tiklanadi, yangi sahifada tepaga chiqadi. useMatch("/products/:id") — joriy URL berilgan naqshga mos kelishini tekshiradi (mos bo'lsa match obyekti, aks holda null) — bu tab yoki havolaning "faol"ligini aniqlashda foydali (NavLink yetmaydigan holatlar). Breadcrumb (yo'lchi — "Bosh / Mahsulotlar / Telefon") — nested route'lar tabiiy iyerarxiyasidan quriladi: route obyektiga handle: { crumb: "..." } qo'shib, komponentda useMatches() bilan joriy mos route'lar zanjirini olib, breadcrumb yasaysiz. Ikki nuqta: (1) ScrollRestoration SPA'ni server-sayt kabi "tabiiy" his qildiradi (kichik, lekin muhim UX); (2) breadcrumb chuqur nested ilovalarda (dashboard, katalog) foydalanuvchining "qayerdaman" tuyg'usini beradi.


3. Sintaksis — tez ma'lumotnoma

text
SETUP 2.3-bob:       <BrowserRouter><App/></BrowserRouter>  (main.jsx)
ROUTES 2.4-bob:      <Routes><Route path="/x" element={<X/>}/></Routes>
LINK 2.5-bob:        <Link to="/x">  |  <NavLink to="/x" className={({isActive})=>...}>
PARAM 2.6-bob:       <Route path="/u/:id"/>    const { id } = useParams()
NESTED 2.7-bob:      <Route path="/" element={<Layout/>}> <Route path="x"/> </Route>  + <Outlet/>
INDEX/404 2.8-bob:   <Route index element={<Home/>}/>  |  <Route path="*" element={<NotFound/>}/>
NAVIGATE 2.9-bob:    const nav = useNavigate(); nav("/x", { replace: true }) | nav(-1)
QUERY 2.10-bob:      const [sp, setSp] = useSearchParams(); sp.get("page"); setSp({page:"2"})
LOCATION 2.11-bob:   const loc = useLocation(); loc.pathname | loc.state
GUARD 2.12-bob:      {!user && <Navigate to="/login" state={{from}} replace/>}
LOADER 2.13-bob:     createBrowserRouter([{path, element, loader}]) + useLoaderData()
ROUTER 2.15-bob:     <BrowserRouter> (toza URL) | <HashRouter> (/#/) | <MemoryRouter> (test)
SPLAT/OPT 2.16-bob:  path="files/*"  sp["*"]  |  path="/x/:id?" (ixtiyoriy)  |  to="../x" (relative)
ERROR 2.17-bob:      { ..., errorElement: <Err/> } + const e = useRouteError()
PENDING 2.18-bob:    const nav = useNavigation(); nav.state === "loading"  |  defer + <Await>
SCROLL/MATCH2.19-bob:<ScrollRestoration/>  |  const m = useMatch("/x/:id")  |  useMatches()

4. Batafsil kod namunalari

Misol 1 — Setup va asosiy route'lar (2.3, 2.4)

jsx
// main.jsx
import { BrowserRouter } from "react-router-dom";
import { createRoot } from "react-dom/client";
import App from "./App";

createRoot(document.getElementById("root")).render(
  <BrowserRouter>          {/* butun ilovani o'raydi (History API) */}
    <App />
  </BrowserRouter>
);

// App.jsx
import { Routes, Route } from "react-router-dom";
function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/products" element={<Products />} />
      <Route path="/about" element={<About />} />
    </Routes>
  );
}
jsx
import { Link, NavLink } from "react-router-dom";

function Navbar() {
  return (
    <nav>
      {/* oddiy Link */}
      <Link to="/">Logo</Link>

      {/* NavLink — faol sahifa ajralib turadi */}
      <NavLink to="/products" className={({ isActive }) => (isActive ? "active" : "")}>
        Mahsulotlar
      </NavLink>
      <NavLink to="/about" style={({ isActive }) => ({ fontWeight: isActive ? "bold" : "normal" })}>
        Biz haqimizda
      </NavLink>
      <NavLink to="/cart"> Savat</NavLink>
    </nav>
  );
}
//  <a href> ISHLATMA (sahifani qayta yuklaydi — 2.5); ilova ichida har doim Link/NavLink

Misol 3 — Dinamik parametr (useParams — 2.6)

jsx
import { useParams, Link } from "react-router-dom";

// Route: <Route path="/products/:id" element={<ProductDetail />} />
function ProductDetail() {
  const { id } = useParams();                    // URL'dan id (string)
  const { data: product, loading } = useFetch(`/api/products/${id}`);   // 11.7

  if (loading) return <Spinner />;
  return (
    <div>
      <h1>{product.name}</h1>
      <p>{product.price} so'm</p>
      <Link to="/products"> Ro'yxatga qaytish</Link>
    </div>
  );
}

// Ro'yxatda — har mahsulotga dinamik havola:
function Products({ items }) {
  return (
    <ul>
      {items.map(p => (
        <li key={p.id}>
          <Link to={`/products/${p.id}`}>{p.name}</Link>   {/* /products/42 */}
        </li>
      ))}
    </ul>
  );
}

Misol 4 — Nested routes va Outlet (layout — 2.7)

jsx
import { Routes, Route, Outlet, NavLink } from "react-router-dom";

// Umumiy layout (Navbar + o'zgaruvchan kontent + Footer)
function Layout() {
  return (
    <div>
      <header>
        <NavLink to="/">Bosh</NavLink>
        <NavLink to="/products">Mahsulotlar</NavLink>
        <NavLink to="/profile">Profil</NavLink>
      </header>
      <main>
        <Outlet />                {/*  bola route shu yerda render bo'ladi */}
      </main>
      <footer>© 2026</footer>
    </div>
  );
}

function App() {
  return (
    <Routes>
      <Route path="/" element={<Layout />}>       {/* ota — umumiy qobiq */}
        <Route index element={<Home />} />         {/* / */}
        <Route path="products" element={<Products />} />     {/* /products */}
        <Route path="products/:id" element={<ProductDetail />} />  {/* /products/42 */}
        <Route path="profile" element={<Profile />} />
        <Route path="*" element={<NotFound />} />  {/* 404 */}
      </Route>
    </Routes>
  );
}
//  Navbar/Footer o'zgarmaydi (Layout'da); faqat Outlet ichi almashadi (2.7)

Misol 5 — 404 catch-all sahifa (2.8)

jsx
import { Link, useNavigate } from "react-router-dom";

function NotFound() {
  const navigate = useNavigate();
  return (
    <div className="not-found">
      <h1>404</h1>
      <p>Bunday sahifa topilmadi.</p>
      <Link to="/">Bosh sahifaga</Link>
      <button onClick={() => navigate(-1)}> Orqaga</button>   {/* navigate(-1) — orqaga */}
    </div>
  );
}
// Route: <Route path="*" element={<NotFound />} />  (eng oxirda — 2.8)

Misol 6 — useNavigate (login'dan keyin — 2.9)

jsx
import { useNavigate, useLocation } from "react-router-dom";

function LoginForm() {
  const navigate = useNavigate();
  const location = useLocation();
  const from = location.state?.from || "/dashboard";   // qayerga bormoqchi edi (2.11, 2.12)

  async function handleSubmit(e) {
    e.preventDefault();
    const ok = await api.login(/* ... */);
    if (ok) {
      navigate(from, { replace: true });    //  kelgan joyga (yoki dashboard), replace (orqaga login'ga qaytmasin)
    }
  }

  return <form onSubmit={handleSubmit}>{/* ... */}</form>;
}
//  replace: true — login muvaffaqiyatli bo'lgach, "orqaga" bossa login'ga emas, oldingisi (2.9)

Misol 7 — useSearchParams (filtr + sahifalash — 2.10)

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

function ProductList({ allProducts }) {
  const [searchParams, setSearchParams] = useSearchParams();
  const category = searchParams.get("category") || "all";
  const sort = searchParams.get("sort") || "name";
  const page = Number(searchParams.get("page")) || 1;

  function updateFilter(key, value) {
    setSearchParams(prev => {
      prev.set(key, value);          // mavjud query'ni saqlab, bittasini yangila
      if (key !== "page") prev.set("page", "1");   // filtr o'zgarca 1-sahifaga
      return prev;
    });
  }

  const filtered = allProducts
    .filter(p => category === "all" || p.category === category)
    .sort((a, b) => (sort === "price" ? a.price - b.price : a.name.localeCompare(b.name)));

  return (
    <div>
      <select value={category} onChange={e => updateFilter("category", e.target.value)}>
        <option value="all">Hammasi</option>
        <option value="phones">Telefonlar</option>
      </select>
      <select value={sort} onChange={e => updateFilter("sort", e.target.value)}>
        <option value="name">Nom</option>
        <option value="price">Narx</option>
      </select>
      <ul>{filtered.map(p => <li key={p.id}>{p.name}</li>)}</ul>
    </div>
  );
}
//  Filtr URL'da (/products?category=phones&sort=price)  ulashib/saqlab/orqaga ishlaydi (2.10)

Misol 8 — Protected route (auth guard — 2.12)

jsx
import { Navigate, useLocation } from "react-router-dom";
import { useAuth } from "../hooks/useAuth";       // 11.7

function ProtectedRoute({ children }) {
  const { user, loading } = useAuth();
  const location = useLocation();

  if (loading) return <Spinner />;                // auth holatini tekshirmoqda
  if (!user) {
    // kirmagan  login'ga (qayerga bormoqchi edi — saqla — 2.11)
    return <Navigate to="/login" state={{ from: location.pathname }} replace />;
  }
  return children;                                 // kirgan  sahifa
}

// Ishlatish:
function App() {
  return (
    <Routes>
      <Route path="/login" element={<Login />} />
      <Route path="/dashboard" element={
        <ProtectedRoute><Dashboard /></ProtectedRoute>
      } />
    </Routes>
  );
}
//  Frontend guard — UX; HAQIQIY himoya backend'da (token — 5.16, 14)

Misol 9 — Role-based protected route (rol bo'yicha — 2.12)

jsx
function RoleRoute({ children, allowedRoles }) {
  const { user } = useAuth();
  if (!user) return <Navigate to="/login" replace />;
  if (!allowedRoles.includes(user.role)) {
    return <Navigate to="/403" replace />;        // ruxsat yo'q (rol mos emas)
  }
  return children;
}

// Faqat admin:
<Route path="/admin" element={
  <RoleRoute allowedRoles={["admin"]}><AdminPanel /></RoleRoute>
} />
//  RBAC frontend (UX) + backend (haqiqiy — 5.17) birga (14-QISM)

Misol 10 — Protected layout (guruh route himoyasi — 2.7, 2.12)

jsx
// Barcha bola route'ni birata himoyalash (Outlet bilan)
function ProtectedLayout() {
  const { user } = useAuth();
  if (!user) return <Navigate to="/login" replace />;
  return (
    <DashboardLayout>
      <Outlet />                {/* himoyalangan bola route'lar */}
    </DashboardLayout>
  );
}

function App() {
  return (
    <Routes>
      <Route path="/login" element={<Login />} />
      <Route element={<ProtectedLayout />}>        {/* path'siz — faqat himoya + layout */}
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/settings" element={<Settings />} />
        <Route path="/profile" element={<Profile />} />
      </Route>
    </Routes>
  );
}
//  Bitta ProtectedLayout — dashboard/settings/profile hammasini himoyalaydi (DRY — 2.7)

Misol 11 — Lazy routes (code splitting bilan — 2.13, 11.8)

jsx
import { lazy, Suspense } from "react";
import { Routes, Route } from "react-router-dom";

const Home = lazy(() => import("./pages/Home"));
const Dashboard = lazy(() => import("./pages/Dashboard"));
const Settings = lazy(() => import("./pages/Settings"));

function App() {
  return (
    <Suspense fallback={<PageLoader />}>    {/* sahifa yuklanishda (11.8: 2.5) */}
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/settings" element={<Settings />} />
      </Routes>
    </Suspense>
  );
}
//  Har sahifa alohida chunk (route-based splitting — 11.8: 2.6); routing + lazy birga

Misol 12 — Dasturiy navigatsiya naqshlari (2.9)

jsx
function Examples() {
  const navigate = useNavigate();
  return (
    <div>
      <button onClick={() => navigate("/products")}>Mahsulotlar</button>
      <button onClick={() => navigate(-1)}> Orqaga</button>
      <button onClick={() => navigate("/cart", { state: { fromProduct: true } })}>
        Savatga (ma'lumot bilan)
      </button>
      {/* Shartli yo'naltirish (taymer/effekt) */}
    </div>
  );
}

// Effektda yo'naltirish (masalan 5s'dan keyin):
function Success() {
  const navigate = useNavigate();
  useEffect(() => {
    const timer = setTimeout(() => navigate("/dashboard"), 5000);   // 5s keyin
    return () => clearTimeout(timer);            // cleanup (11.5: 2.7)
  }, [navigate]);
  return <p>5 soniyada yo'naltirilasiz...</p>;
}

Misol 13 — Data router: loader bilan (2.13)

jsx
import { createBrowserRouter, RouterProvider, useLoaderData } from "react-router-dom";

// Route config (data API)
const router = createBrowserRouter([
  {
    path: "/",
    element: <Layout />,
    children: [
      { index: true, element: <Home /> },
      {
        path: "products/:id",
        element: <ProductDetail />,
        loader: async ({ params }) => {          //  render'dan OLDIN ma'lumot
          const res = await fetch(`/api/products/${params.id}`);
          if (!res.ok) throw new Response("Topilmadi", { status: 404 });
          return res.json();
        },
      },
    ],
  },
]);

function ProductDetail() {
  const product = useLoaderData();               // loader qaytargan (tayyor) ma'lumot
  return <h1>{product.name}</h1>;                // loading holati YO'Q (loader yuklab bo'lgan)
}

function App() {
  return <RouterProvider router={router} />;
}
//  loader — render'dan oldin ma'lumot (tezroq; loading komponentda emas — 2.13)

Misol 14 — To'liq routing strukturasi (umumiy)

jsx
import { Routes, Route } from "react-router-dom";
import { lazy, Suspense } from "react";

const Home = lazy(() => import("./pages/Home"));
const Products = lazy(() => import("./pages/Products"));
const ProductDetail = lazy(() => import("./pages/ProductDetail"));
const Dashboard = lazy(() => import("./pages/Dashboard"));
const Login = lazy(() => import("./pages/Login"));

function App() {
  return (
    <Suspense fallback={<PageLoader />}>
      <Routes>
        {/* Ochiq (public) — umumiy layout */}
        <Route path="/" element={<PublicLayout />}>
          <Route index element={<Home />} />
          <Route path="products" element={<Products />} />
          <Route path="products/:id" element={<ProductDetail />} />
          <Route path="login" element={<Login />} />
        </Route>

        {/* Himoyalangan — protected layout */}
        <Route element={<ProtectedLayout />}>
          <Route path="/dashboard" element={<Dashboard />} />
          <Route path="/settings" element={<Settings />} />
        </Route>

        {/* Admin — rol bilan */}
        <Route path="/admin" element={<RoleRoute allowedRoles={["admin"]}><Admin /></RoleRoute>} />

        {/* 404 */}
        <Route path="*" element={<NotFound />} />
      </Routes>
    </Suspense>
  );
}
//  Public/protected/admin layout'lar + lazy + 404 — real ilova routing skeleti

Misol 15 — errorElement va useRouteError (data router — 2.17)

jsx
import { createBrowserRouter, useRouteError, useLoaderData } from "react-router-dom";

const router = createBrowserRouter([
  {
    path: "/products/:id",
    element: <ProductDetail />,
    errorElement: <RouteError />,        //  loader/render xatosi shu yerga tushadi
    loader: async ({ params }) => {
      const res = await fetch(`/api/products/${params.id}`);
      if (!res.ok) throw new Response("Topilmadi", { status: res.status });   //  errorElement
      return res.json();
    },
  },
]);

function RouteError() {
  const error = useRouteError();          // ushlangan xato yoki Response
  if (error.status === 404) return <h1>Mahsulot topilmadi</h1>;
  return <div><h1>Xatolik yuz berdi</h1><p>{error.message}</p></div>;
}
//  errorElement — route darajasidagi Error Boundary (11.6 analogi — 2.17)

Misol 16 — Pending UI (useNavigation — 2.18)

jsx
import { useNavigation, Outlet } from "react-router-dom";

// Root layout — o'tishda global "yuklanmoqda" ko'rsatkichi
function RootLayout() {
  const navigation = useNavigation();
  const isLoading = navigation.state === "loading";   // loader ma'lumot yuklamoqda
  return (
    <div>
      {isLoading && <div className="top-progress-bar" />}   {/* silliq UX (oq ekran emas) */}
      <main style={{ opacity: isLoading ? 0.6 : 1 }}>
        <Outlet />
      </main>
    </div>
  );
}
//  navigation.state: "idle" | "loading" | "submitting" — pending UI uchun (2.18)

Misol 17 — Splat, relative navigatsiya va scroll restoration (2.16, 2.19)

jsx
import { ScrollRestoration, Link, useParams, useNavigate } from "react-router-dom";

// Splat: /files/*  butun ostki yo'lni ushlaydi
function FileBrowser() {
  const params = useParams();
  const path = params["*"];               // "docs/2026/hisobot.pdf"
  const navigate = useNavigate();
  return (
    <div>
      <p>Joriy yo'l: {path}</p>
      <button onClick={() => navigate("..")}> Yuqori papka</button>   {/* relative */}
      <Link to="edit">Tahrirlash</Link>    {/* relative — joriy route'ga qo'shiladi */}
    </div>
  );
}

// Root layout'da bir marta — scroll pozitsiyaci avtomatik tiklanadi
function Root() {
  return (
    <>
      <Outlet />
      <ScrollRestoration />               {/* orqaga  eski scroll; yangi  tepaga 2.19-bob */}
    </>
  );
}

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

1) Ilova ichida navigatsiya

text
 <a href="/products">  (sahifani qayta yuklaydi — SPA buziladi — 2.5)
 <Link to="/products">  (client-side — qayta yuklamaydi)

2) element

text
 <Route path="/x" element={Komponent} />  (havola — ishlamaydi)
 <Route path="/x" element={<Komponent />} />  (JSX — 2.4)

3) Param turi

text
 const { id } = useParams(); product[id]  (id — string, raqam kutilsa xato)
 Number(id)  (kerak bo'lsa — 2.6)

4) Login'dan keyin

text
 navigate("/dashboard")  (orqaga bossa login'ga qaytadi)
 navigate(from, { replace: true })  (tarixni almashtir — 2.9)

5) Filtr holati

text
 const [filter, setFilter] = useState()  (ulashib/saqlab bo'lmaydi)
 useSearchParams (URL'da — ulashiladigan — 2.10)

6) Himoya

text
 faqat frontend guard (har kim API'ga to'g'ridan kira oladi — 2.12)
 frontend (UX) + backend token tekshiruvi (haqiqiy — 5.16, 14)

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — useNavigate() may be used only in the context of a <Router> component

Sababi: hook (useNavigate/useParams...) <BrowserRouter> tashqarisida ishlatildi 2.3-bob. Yechimi: BrowserRouter/RouterProviderni ildizda (main.jsx) butun ilovani o'rasin.

Xato 2 — Sahifani yangilaganda 404 (deploy'dan keyin, masalan /products'da)

Sababi: server /products ni bilmaydi (faqat / bor — SPA). Yechimi: server barcha yo'llarni index.htmlga yo'naltirishga sozlanadi (Nginx try_files $uri /index.html — 10.2; Vercel/Netlify avtomatik — 13.11).

Xato 3 — <a href> SPA'ni to'liq qayta yuklaydi

Sababi: ilova ichida oddiy <a> ishlatildi 2.5-bob. Yechimi: <Link to="..."> (ichki), <a> faqat tashqi saytlarga.

Xato 4 — NavLink hamma havolada "active" (faqat tepa sahifa kerak)

Sababi: / har doim mos keladi (boshqa yo'llar / bilan boshlanadi). Yechimi: <NavLink to="/" end> (end — aniq mos, faqat /da active).

Xato 5 — Nested route ko'rinmaydi (faqat layout)

Sababi: Layout'da <Outlet /> yo'q 2.7-bob. Yechimi: Layout komponentida bola route o'rniga <Outlet /> qo'shiladi.

Xato 6 — Protected route login'dan keyin oldingi sahifaga qaytmaydi

Sababi: from saqlanmadi yoki ishlatilmadi (2.11, 2.12). Yechimi: guard'da state={{ from: location.pathname }}, login'da navigate(from).

Xato 7 — useSearchParams o'zgartirishda boshqa query yo'qoladi

Sababi: setSearchParams({ page: "2" }) — butun query'ni almashtiradi. Yechimi: setSearchParams(prev => { prev.set("page","2"); return prev; }) (mavjudni saqlash — Misol 7).


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • SPA (11.3: 2.10): routing — SPA'da "sahifalar" yaratish usuli (URL UI).
  • Code splitting 11.8-bob: route-based splitting — har sahifa lazy (Misol 11).
  • Auth (11.7, 5.16): protected routes — useAuth + Navigate (Misol 8).
  • State 11.4-bob: URL — holatning bir turi (query — useState'dan afzal filtr uchun — 2.10).
  • Data fetching 12.4-bob: loader yoki useParams + Query (mahsulot tafsiloti — 2.6, 2.13).
  • Layout 11.2-bob: nested routes + Outlet — umumiy layout 2.7-bob.
  • Deploy (10.2, 13.11): server SPA fallback (Nginx try_files — Xato 2).
  • Next.js 13.2-bob: file-based routing — React Router'ning avtomatik muqobili.

8. Eng yaxshi amaliyotlar (best practices)

  • Faqat <Link>/<NavLink> ilova ichida (<a> SPA'ni buzadi — 2.5).
  • Nested routes + Outlet (umumiy layout — takror yo'q — 2.7).
  • Index route + 404 catch-all (default va noto'g'ri URL — UX — 2.8).
  • Filtr/sahifani query'da (useSearchParams — ulashiladigan — 2.10).
  • Protected route (auth guard + from saqlash — 2.12); backend bilan birga (xavfsizlik).
  • replace: true login/forma'dan keyin (orqaga qaytarmasin — 2.9).
  • Route-based lazy (har sahifa alohida chunk — tez — 11.8, Misol 11).
  • Server SPA fallback (deploy'da barcha yo'l index.html — Xato 2).
  • useParams qiymatini o'girish (string Number kerak bo'lsa — 2.6).
  • Routing arxitekturasini tashkil etish (pages/, routes/, Layout — 2.14).

9. Amaliy loyiha: "Ko'p Sahifali Onlayn Do'kon (Routing)"

To'liq routing skeletli onlayn do'kon — public, protected va dinamik sahifalar bilan.

Maqsad

React Router bilan to'liq navigatsiyali e-commerce SPA: mahsulotlar, mahsulot tafsiloti, savat, login, himoyalangan profil/dashboard.

Talablar (requirements)

  1. Setup + layout: BrowserRouter + nested layout (Navbar + Outlet + Footer — Misol 1, 4).
  2. Sahifalar: Bosh, Mahsulotlar, Mahsulot tafsiloti (/products/:id), Savat, Login, Profil.
  3. NavLink: navbar'da faol sahifa ajralib tursin (end bilan bosh sahifa — Misol 2, Xato 4).
  4. Dinamik route: /products/:id + useParams bilan mahsulot ko'rsatish (Misol 3, 2.6).
  5. Filtr query'da: mahsulotlar sahifasida kategoriya/saralash useSearchParams (Misol 7, 2.10).
  6. Protected: Profil/Dashboard faqat login bo'lganda (ProtectedRoute/Layout — Misol 8, 10).
  7. Login oqimi: login'dan keyin oldingi sahifaga qaytish (from + replace — Misol 6, 2.9).
  8. 404: catch-all NotFound + orqaga tugmasi (Misol 5, 2.8).
  9. Lazy routes: har sahifa lazy + Suspense (Misol 11, 11.8).
  10. Dasturiy navigatsiya: "Savatga qo'shildi" navigate bilan o'tish (Misol 12).

Maslahatlar (hint)

  • BrowserRouterni main.jsxda eng tepaga qo'ying (Xato 1).
  • Layout'da <Outlet />ni unutmang (aks holda bola route ko'rinmaydi — Xato 5).
  • useParams().id — string; raqam kerak bo'lsa Number(id) 2.6-bob.
  • Filtr/sahifani useState emas, useSearchParamsda saqlang (ulashiladigan — 2.10).
  • Protected guard — frontend (UX); haqiqiy himoya backend token bilan 2.12-bob.
  • Deploy qilsangiz — server SPA fallback sozlang (/productsda yangilaganda 404 bo'lmasin — Xato 2).

"Tayyor" mezonlari (acceptance criteria)

  • Barcha sahifalar route bilan ulangan, navbar ishlaydi.
  • NavLink faol sahifani to'g'ri ko'rsatadi (end bilan).
  • /products/:id dinamik sahifa ishlaydi.
  • Filtr URL query'da (ulashiladigan, orqaga ishlaydi).
  • Profil/Dashboard himoyalangan (kirmagan login).
  • Login'dan keyin oldingi sahifaga qaytadi (replace bilan).
  • 404 sahifa noto'g'ri URL'da ishlaydi.
  • Har sahifa lazy (Network'da alohida chunk).
  • <a> ishlatilmagan (faqat Link/NavLink).

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


10. Xulosa va keyingi bobga ko'prik

Bu bobda ko'p sahifali ilova skeletini — routing'ni — chuqur o'rgandik:

  • Nega routing (URL UI — 2.1); client-side vs server (History API — 2.2); setup (BrowserRouter/createBrowserRouter — 2.3); Routes/Route 2.4-bob.
  • Link/NavLink 2.5-bob; dinamik segment va useParams 2.6-bob; nested routes va Outlet (layout — 2.7); index va 404 2.8-bob.
  • useNavigate (dasturiy — 2.9); useSearchParams (query — 2.10); useLocation 2.11-bob; protected routes 2.12-bob; lazy routes va loader 2.13-bob; v6/v7 arxitektura 2.14-bob.
  • Router turlari (Browser/Hash/Memory — 2.15); splat, optional segment, relative/absolute yo'l 2.16-bob; errorElement va useRouteError 2.17-bob; pending UI (useNavigation), defer/Await 2.18-bob; scroll restoration, useMatch, breadcrumb 2.19-bob.

Endi siz ko'p sahifali, himoyalangan, filtrlanadigan, tez (lazy) ilova qura olasiz — URL holatni boshqaradi, layout takrorlanmaydi, navigatsiya silliq. Bu — har real React ilovasining skeletini tashkil qiladi.

Keyingi bob — 11.10-bob: Formalar — React Hook Form + Zod validation. Forma — har ilovaning eng ko'p uchraydigan, lekin eng ko'p og'riq beradigan qismi (login, ro'yxat, checkout, sozlamalar). 11.4'da controlled inputs'ni qo'lda boshqardik — bu kichik formada mayli, lekin katta formada (10+ maydon, murakkab validatsiya) chidab bo'lmaydi. React Hook Form formani samarali (kam re-render) va sodda boshqaradi, Zod esa validatsiya sxemasini (qoidalarni) deklarativ va type-safe yozadi. Bu ikkisi — zamonaviy React forma standartining oltin juftligi.


Foydalanilgan rasmiy/ishonchli manbalar

  • React Router rasmiy hujjati — Routes/Route, Link/NavLink, useParams, useNavigate, useSearchParams, nested routes va Outlet, index route, lazy
  • React Router rasmiy hujjati — BrowserRouter/HashRouter/MemoryRouter, splat va optional segment, relative/absolute yo'l
  • React Router rasmiy hujjati — data router (createBrowserRouter, RouterProvider), loader/action, useLoaderData/useActionData, defer/Await
  • React Router rasmiy hujjati — errorElement/useRouteError, useNavigation (pending UI), ScrollRestoration, useMatch/useMatches, "Protected Routes", v6/v7 migratsiya
  • MDN Web Docs — History API (pushState, popstate), URL/URLSearchParams
  • web.dev — SPA routing, Core Web Vitals; server SPA fallback (Nginx try_files — 10.2)

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
11.9-bob: Routing (React Router) — Wisar