Pas pertama kamu klik link di Tokopedia — perhatiin: URL berubah, konten berubah, tapi PAGE GAK RELOAD. Tab browser gak flicker, gak ada white screen sebentar, smooth banget. Itu client-side routing: JavaScript yang nanggepin URL change, swap konten React tanpa request HTML baru ke server. Kontras dengan classic web (PHP/server-rendered) tiap link = full reload, lambat. React Router library paling populer buat pattern ini — ngasih <Routes>, <Link>, dan hook useParams/useNavigate buat akses route data.
💡 2026 alternatives. React Router dominan, tapi alternative bagus juga: TanStack Router (type-safe, pakai di project ini), Next.js App Router (file-based), Remix (web standards-first). Konsep dasarnya sama — yang dipelajari di sini transferable. Project hypersheets-frontend pakai TanStack Router.
Konsep Dasar
import { BrowserRouter, Routes, Route } from "react-router-dom"
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users/:id" element={<UserDetail />} />
</Routes>
</BrowserRouter>
)
}
URL match path → render element. :id = dynamic param.
Link Navigation — JANGAN <a href>
import { Link } from "react-router-dom"
function Navbar() {
return (
<nav>
<Link to="/">Home</Link> {/* ✓ no reload */}
<Link to="/about">About</Link> {/* ✓ no reload */}
<a href="/about">About</a> {/* ✗ FULL RELOAD */}
</nav>
)
}
<Link> intercept klik → JavaScript yang handle navigation. <a href> = browser reload halaman penuh.
Dynamic Route Parameters
import { useParams } from "react-router-dom"
// Route: /users/:id
function UserDetail() {
const { id } = useParams() // ambil dari URL
// .../users/42 → id = "42"
return <h1>User #{id}</h1>
}
Programmatic Navigation
import { useNavigate } from "react-router-dom"
function LoginButton() {
const navigate = useNavigate()
const handleLogin = async () => {
await login(...)
navigate("/dashboard") // pindah halaman dari kode
}
return <button onClick={handleLogin}>Login</button>
}
Nested Routes — Layout Pattern
<Routes>
<Route path="/" element={<Layout />}> {/* parent */}
<Route index element={<Home />} /> {/* "/" */}
<Route path="about" element={<About />} /> {/* "/about" */}
<Route path="users/:id" element={<UserDetail />} />
</Route>
</Routes>
// Di Layout:
function Layout() {
return (
<div>
<Navbar />
<main>
<Outlet /> {/* tempat child route render */}
</main>
</div>
)
}
🎭 Analogi sehari-hari
React Router itu kayak mall dengan zona-zona berbeda di lantai sama. URL = papan petunjuk arah. Pas kamu jalan dari food court ke department store, kamu gak naik lift atau ganti gedung — cukup belok di koridor (router intercept), suasana berubah (komponen swap), tapi kamu masih di mall yang sama (gak reload). <Link> = papan petunjuk yang kamu ikutin. useParams = nomor toko di papan ("Toko #42, Kosmetik"). Kalau pake <a href> = harus keluar mall, jalan kaki ke gedung lain, masuk lagi (full reload — capek + lama).
⚠️ Jebakan yang sering ditemui
- Pakai
<a href>instead of<Link to>— full page reload, state hilang. SELALU<Link>untuk internal navigation.<a>cuma untuk EXTERNAL link. useNavigategak jalan di luar component — hook, harus dipanggil di body component. Buat util navigation, return navigate dari context atau ref.- Lupa
<BrowserRouter>wrap App —<Link>lempar error "Cannot read properties of null". Wrap di root. - Path matching strict di v6 —
/usersGAK match/users/42. Pakai nested route atau wildcard*. - Forget
indexroute — nested route butuh<Route index>untuk match parent path exactly. useParamsreturns string always —useParams()value SELALU string. Convert manual:Number(id).- Search params vs route params bingung —
/users/42(route) vs/users?id=42(search). UseuseParamsuntuk route,useSearchParamsuntuk query. - State lost saat navigate — pindah route = unmount component, state hilang. Lift state ke parent atau pakai URL/global state.
🎯 Pilih state location — di mana?
- Route (segment URL) →
/users/:id→useParams(untuk identitas resource)- Search params (query string) →
/users?filter=active→useSearchParams(untuk filter, page, sort)- Component state →
useState(untuk UI ephemeral, modal open/close)- Context →
useContext(untuk global app state)- Server state → TanStack Query (untuk API data)
Pattern bagus: state yang kamu mau SHAREABLE/BOOKMARK-ABLE → URL (route or search). State internal UI → component state. Aturan praktis: kalau user-mu mau bisa share link "ini hasil filter saya", taro di URL.
TL;DR: React Router = client-side routing — URL berubah tanpa reload page. Setup: <BrowserRouter><Routes><Route path="..." element={<X />} /></Routes></BrowserRouter>. Navigate: <Link to="/path"> (BUKAN <a href>!) atau programmatic useNavigate(). Dynamic param: :id → useParams() (always string). Layout pattern: nested route + <Outlet />. Alternatives: TanStack Router (type-safe, project ini), Next.js App Router. URL = state yang shareable.