Episode ini mengajarkan React Router: BrowserRouter, Routes, dan Route untuk mendefinisikan halaman, nested routes dengan dynamic params, route guards untuk proteksi, serta Link, NavLink, dan redirect. Kalian juga belajar code splitting berbasis route.

Aplikasi yang hanya punya satu halaman cepat sampai batasnya. React Router adalah standar de facto untuk navigasi di React SPA — library yang membuat URL menjadi sumber kebenaran bagi halaman yang ditampilkan.
Episode 9 membangun dari dasar: BrowserRouter, Routes, dan Route, lalu meningkat ke nested routes, dynamic params, route guards, Link, NavLink, dan redirect. Terakhir, kita menerapkan code splitting berbasis route dengan lazy dan Suspense supaya tiap halaman dimuat terpisah.
Mulai dengan menginstall dan membungkus aplikasi dengan BrowserRouter:
npm install react-router-domimport { BrowserRouter, Routes, Route, Link } from "react-router-dom"
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Beranda</Link>
<Link to="/tentang">Tentang</Link>
</nav>
<Routes>
<Route path="/" element={<h1>Beranda</h1>} />
<Route path="/tentang" element={<h1>Tentang Kami</h1>} />
</Routes>
</BrowserRouter>
)
}<BrowserRouter>{:javascript}</BrowserRouter> menyediakan konteks URL ke seluruh aplikasi, dan <Routes> menampung daftar <Route> yang dicocokkan dengan path. Link menggantikan <a> agar navigasi terjadi tanpa reload penuh.
Untuk layout bersama (header, sidebar) di banyak halaman, pakai route induk dengan <Outlet>:
import { Routes, Route, Outlet } from "react-router-dom"
function Layout() {
return (
<div>
<header>Header Bersama</header>
<Outlet />
</div>
)
}
function App() {
return (
<Routes>
<Route element={<Layout />}>
<Route path="/" element={<h1>Beranda</h1>} />
<Route path="/blog" element={<h1>Blog</h1>} />
</Route>
</Routes>
)
}<Outlet /> adalah tempat route anak dirender. Layout seperti header dan footer ditulis sekali, dan setiap halaman muncul di dalamnya.
Path bisa berisi parameter dinamis dengan awalan titik dua:
import { useParams } from "react-router-dom"
function DetailProduk() {
const { id } = useParams()
return <h1>Produk {id}</h1>
}
// rute: <Route path="/produk/:id" element={<DetailProduk />} />const { id } = useParams() membaca nilai dari URL seperti /produk/42. Parameter dinamis membuat satu komponen melayani banyak halaman.
Route guards melindungi halaman yang butuh autentikasi. Pola sederhananya: periksa kondisi, lalu render <Navigate> jika tidak berhak:
import { Navigate } from "react-router-dom"
function HalamanProteksi({ login, anak }) {
if (!login) return <Navigate to="/login" replace />
return anak
}<Navigate to="/login" replace /> mengalihkan pengguna yang belum login ke halaman login. replace mengganti entri history sehingga tombol back tidak kembali ke halaman terproteksi. Episode 12 akan membuat pola autentikasi penuh.
NavLink bekerja seperti Link plus tahu kapan dirinya aktif — berguna untuk menu dengan gaya aktif:
import { NavLink } from "react-router-dom"
<NavLink
to="/dashboard"
className={({ isActive }) => (isActive ? "menu aktif" : "menu")}
>
Dashboard
</NavLink>className={({ isActive }) => isActive ? "menu aktif" : "menu"{:javascript}} memberi class berbeda saat route aktif. Menu navigasi langsung terlihat di halaman mana pengguna berada.
Halaman besar bisa dimuat terpisah supaya bundle awal tetap kecil. React menyediakan lazy dan Suspense:
import { lazy, Suspense } from "react"
const Dashboard = lazy(() => import("./Dashboard.jsx"))
function App() {
return (
<Suspense fallback={<p>Memuat halaman...</p>}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Suspense>
)
}lazy(() => import("./Dashboard.jsx")) membuat Vite memecah Dashboard menjadi chunk terpisah yang baru diunduh saat route tersebut dikunjungi. fallback ditampilkan selama proses unduh berlangsung.
npm run buildPerhatikan output build: folder dist/assets berisi beberapa file .js terpisah, masing-masing untuk satu route. Ini adalah dasar networking performance yang akan kita optimalkan di episode 14.
Episode 9 memberi aplikasi kalian banyak halaman: dasar BrowserRouter, Routes, dan Route, nested routes dengan Outlet, dynamic params, route guards, Link, NavLink, redirect, dan code splitting per route dengan lazy plus Suspense.
Inti yang harus dibawa pulang:
BrowserRouter membungkus aplikasi; Routes dan Route mendefinisikan halaman.Outlet merender route anak di dalam layout bersama.useParams membaca dynamic params dari URL.<Navigate> untuk mengalihkan pengguna yang tidak berhak.NavLink memberi tanda halaman aktif; useNavigate untuk navigasi programatik.lazy + Suspense memecah bundle per route.Di episode 10 selanjutnya kita akan membahas state management modern — Context API untuk shared state, useReducer untuk logika state kompleks, lalu Zustand dan Redux Toolkit sebagai state manager modern, serta best practice global state versus local state. Kalian akan berhenti menyalurkan props berantai yang panjang.