Nested Routes — ichma-ich route lar, Outlet
Muammodan boshlaylik
Siz dashboard (boshqaruv paneli) yozyapsiz. Har bir sahifada yon menyu va yuqori sarlavha bir xil ko'rinadi. Faqat markaziy qism o'zgaradi:
┌─────────────────────────────────────────┐
│ Dashboard sarlavhasi [Profil] │ ← har doim
├──────────────┬──────────────────────────┤
│ Yon menyu │ /dashboard/statistika │
│ │ │
│ Statistika │ Bu yerda faqat │ ← o'zgaradi
│ Foydalanuvch │ statistika ko'rinadi │
│ Sozlamalar │ │
│ │ │
└──────────────┴──────────────────────────┘
Har bir sahifa uchun alohida Route yozib, yon menyuni qayta-qayta chiqarsangiz — kodning takrorlanishi ko'payadi. Yangi sahifa qo'shilsa, menyuni yana bir joyda qo'shishni eslab qolish kerak.
Nested Routes aynan shu muammo uchun — umumiy qism bir marta yoziladi, faqat o'zgaradigan qism har Route uchun alohida bo'ladi.
Nested Routes nima?
Nested Routes — Route larning ichma-ich joylashtirilishi. Ota Route umumiy layoutni ko'rsatadi. Bola Route lar esa o'sha layout ichidagi o'zgaruvchi qismni ko'rsatadi.
Hayotiy o'xshatma: ofis binosi. Bino bir xil — kirish, liftlar, koridorlar. Lekin har qavat har xil — 1-qavat marketing, 2-qavat texniklar, 3-qavat menejment. Bino qayta qurilmaydi, faqat qavat o'zgaradi.
Nested Routes da bino = ota Route (layout), qavat = bola Route.
Outlet nima?
<Outlet /> — ota Route ning shablonida bola Route ning
ko'rsatiladigan joyi. "Bu yerga bola Route ni joylashtir"
degan belgi.
import { Outlet } from 'react-router-dom';
function DashboardLayout() {
return (
<div>
<header>Dashboard</header>
<aside>Yon menyu</aside>
<main>
<Outlet /> {/* ← bola Route shu yerda chiqadi */}
</main>
</div>
);
}
Asosiy tuzilish
// App.jsx
import { Routes, Route } from 'react-router-dom';
<Routes>
<Route path="/dashboard" element={<DashboardLayout />}>
{/* Bola Route lar — path "/" bilan boshlanmaydi */}
<Route index element={<DashboardBosh />} />
<Route path="statistika" element={<Statistika />} />
<Route path="foydalanuvchilar" element={<Foydalanuvchilar />} />
<Route path="sozlamalar" element={<Sozlamalar />} />
</Route>
</Routes>
URL → ko'rsatiladigan komponent:
/dashboard→DashboardLayout+DashboardBosh(index)/dashboard/statistika→DashboardLayout+Statistika/dashboard/foydalanuvchilar→DashboardLayout+Foydalanuvchilar/dashboard/sozlamalar→DashboardLayout+Sozlamalar
Har safar DashboardLayout ko'rinadi, faqat <Outlet /> joyi o'zgaradi.
index Route — ota manzilning bosh sahifasi
index prop li Route — ota Route ning URL iga to'g'ri kelganda
ko'rsatiladi. /dashboard ga kirganda nima ko'rsatilsin?
Aynan index Route.
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardBosh />} /> {/* /dashboard */}
<Route path="statistika" element={<Statistika />} /> {/* /dashboard/statistika */}
</Route>
index Route da path yo'q — ota Route ning manzili uning manzili.
To'liq misol — Dashboard
Papkalar tuzilishi:
src/
layouts/
DashboardLayout.jsx
pages/
dashboard/
DashboardBosh.jsx
Statistika.jsx
Foydalanuvchilar.jsx
Sozlamalar.jsx
App.jsx
layouts/DashboardLayout.jsx:
import { Outlet, NavLink } from 'react-router-dom';
import styles from './DashboardLayout.module.css';
const menyuBandlari = [
{ to: '/dashboard', label: 'Bosh', end: true },
{ to: '/dashboard/statistika', label: 'Statistika' },
{ to: '/dashboard/foydalanuvchilar', label: 'Foydalanuvchilar' },
{ to: '/dashboard/sozlamalar', label: 'Sozlamalar' },
];
function DashboardLayout() {
return (
<div className={styles.wrapper}>
<header className={styles.sarlavha}>
<h2>Boshqaruv paneli</h2>
</header>
<div className={styles.kontent}>
<aside className={styles.menyu}>
{menyuBandlari.map(({ to, label, end }) => (
<NavLink
key={to}
to={to}
end={end}
className={({ isActive }) =>
isActive ? styles.havola + ' ' + styles.faol : styles.havola
}
>
{label}
</NavLink>
))}
</aside>
<main className={styles.asosiy}>
<Outlet /> {/* ← bola Route shu yerga chiqadi */}
</main>
</div>
</div>
);
}
export default DashboardLayout;
App.jsx:
import { Routes, Route } from 'react-router-dom';
import DashboardLayout from './layouts/DashboardLayout';
import DashboardBosh from './pages/dashboard/DashboardBosh';
import Statistika from './pages/dashboard/Statistika';
import Foydalanuvchilar from './pages/dashboard/Foydalanuvchilar';
import Sozlamalar from './pages/dashboard/Sozlamalar';
import Bosh from './pages/Bosh';
import TopilmadI from './pages/TopilmadI';
function App() {
return (
<Routes>
<Route path="/" element={<Bosh />} />
{/* Dashboard — nested routes */}
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardBosh />} />
<Route path="statistika" element={<Statistika />} />
<Route path="foydalanuvchilar" element={<Foydalanuvchilar />} />
<Route path="sozlamalar" element={<Sozlamalar />} />
</Route>
<Route path="*" element={<TopilmadI />} />
</Routes>
);
}
export default App;
pages/dashboard/DashboardBosh.jsx:
function DashboardBosh() {
return (
<div>
<h1>Xush kelibsiz!</h1>
<p>Chap menyudan bo'limni tanlang.</p>
</div>
);
}
export default DashboardBosh;
pages/dashboard/Statistika.jsx:
function Statistika() {
return (
<div>
<h1>Statistika</h1>
<p>Bu yerda grafiklar bo'ladi.</p>
</div>
);
}
export default Statistika;
Ko'p darajali nested routes
Nested routes faqat ikki darajali bo'lishi shart emas. Uch, to'rt daraja ham bo'lishi mumkin:
<Routes>
<Route path="/ilova" element={<IlovaLayout />}>
<Route path="mahsulotlar" element={<MahsulotlarLayout />}>
<Route index element={<MahsulotlarRoyxat />} />
<Route path=":id" element={<MahsulotDetali />} />
<Route path=":id/tahrir" element={<MahsulotTahrir />} />
</Route>
<Route path="buyurtmalar" element={<Buyurtmalar />} />
</Route>
</Routes>
URL → natija:
/ilova/mahsulotlar→IlovaLayout+MahsulotlarLayout+MahsulotlarRoyxat/ilova/mahsulotlar/42→IlovaLayout+MahsulotlarLayout+MahsulotDetali/ilova/mahsulotlar/42/tahrir→IlovaLayout+MahsulotlarLayout+MahsulotTahrir/ilova/buyurtmalar→IlovaLayout+Buyurtmalar
Har daraja o'zining <Outlet /> ini ko'rsatadi.
Outlet ga ma'lumot uzatish
Ota Route bola Route ga useOutletContext orqali ma'lumot uzata oladi:
import { Outlet } from 'react-router-dom';
function DashboardLayout() {
const foydalanuvchi = { ism: 'Jasur', rol: 'admin' };
return (
<div>
<Outlet context={foydalanuvchi} /> {/* ← context uzatilmoqda */}
</div>
);
}
import { useOutletContext } from 'react-router-dom';
function Statistika() {
const foydalanuvchi = useOutletContext(); // ← context olinmoqda
return <h1>Salom, {foydalanuvchi.ism}!</h1>;
}
Lekin bu ko'p ishlatilmaydi — odatda Context API yoki global state bilan hal qilinadi. Faqat oddiy holatlarda qulay.
Tez-tez uchraydigan xatolar
1. Ota layout da <Outlet /> ni unutish
// ❌ Xato — Outlet yo'q
function DashboardLayout() {
return (
<div>
<aside>Menyu</aside>
<main>
{/* Outlet yo'q — bola Route lar hech qachon ko'rinmaydi */}
</main>
</div>
);
}
// ✅ To'g'ri
function DashboardLayout() {
return (
<div>
<aside>Menyu</aside>
<main>
<Outlet /> {/* ← shu yerga bola Route chiqadi */}
</main>
</div>
);
}
Sababi: <Outlet /> bo'lmasa React Router bola Route ni
qayerga joylashtirish kerakligini bilmaydi. Bola Route lar
tanlanadi, lekin ekranda hech narsa ko'rinmaydi.
2. Bola Route path da / bilan boshlash
// ❌ Xato — bola route path "/" bilan boshlanmoqda
<Route path="/dashboard" element={<DashboardLayout />}>
<Route path="/dashboard/statistika" element={<Statistika />} />
</Route>
// ✅ To'g'ri — faqat qo'shimcha qism
<Route path="/dashboard" element={<DashboardLayout />}>
<Route path="statistika" element={<Statistika />} />
</Route>
Sababi: Bola Route path ota Route path iga avtomatik qo'shiladi.
/dashboard + statistika = /dashboard/statistika. Agar /
bilan boshlasangiz — mutlaq yo'l bo'lib, ota-bola munosabati
buziladi va Route to'g'ri ishlamaydi.
3. index o'rniga path="/" yozish
// ❌ Xato — nested route da path="/"
<Route path="/dashboard" element={<DashboardLayout />}>
<Route path="/" element={<DashboardBosh />} />
</Route>
// ✅ To'g'ri — index prop
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardBosh />} />
</Route>
Sababi: path="/" nested Route da noto'g'ri — u mutlaq manzilga
ishora qiladi. index prop esa "ota Route ning URL i bilan bir xil
bo'lganda ko'rsat" degan ma'no beradi.
4. NavLink da noto'g'ri to manzil
// ❌ Xato — to da ota path yo'q
<NavLink to="statistika">Statistika</NavLink>
// Natija: joriy URL ga "statistika" qo'shiladi
// /dashboard da ishlaydi, lekin /dashboard/boshqa yerda buzilib ketadi
// ✅ To'g'ri — to'liq manzil
<NavLink to="/dashboard/statistika">Statistika</NavLink>
Sababi: Nisbiy to joriy URL ga qarab ishlaydi — turgan
joyingizga qarab har xil natija beradi. Menyu havolalarida
har doim mutlaq manzil (/ bilan boshlanadigan) ishlating.
Xulosa
- Nested Routes — umumiy layout bir marta, faqat o'zgaruvchi qism alohida
<Outlet />— ota layout da bola Route ni chiqarish joyiindex— ota Route URL iga to'g'ri kelganda ko'rsatiladigan bola Route- Bola Route
pathda/boshlanmaydi — faqat qo'shimcha qism yoziladi <Outlet context={...}>vauseOutletContext()— ota-bola ma'lumot uzatish- Menyu havolalarida to'liq manzil (
/dashboard/statistika) ishlatiladi
Keyingi dars: 46-dars: Protected Route — faqat login qilganlar uchun