React
Chapter 12: React Router v6+ — Client-side routing, dynamic URL parameters, nested routes with Outlet, NavLink active states, and protected route guards.
1. Client-Side Routing (SPA Navigation)
In traditional multi-page websites, clicking a link causes the browser to request a brand-new HTML document from the server, causing a blank white screen flash. In a React Single Page Application (SPA), React Router intercepts URL changes and renders the corresponding component tree instantaneously without refreshing the browser.
💡 Real-World Analogy: Stage Curtain Backdrop Switcher
Think of visiting different pages on a website:
- Server-Side Routing (Old Web): Tearing down the entire theater building and constructing a new theater down the street just to change from Act 1 to Act 2!
- Client-Side Routing (React Router): The theater (SPA container) stays put. The stagehands simply swap the painted background curtain (
<Dashboard />$\rightarrow$<Profile />) smoothly in milliseconds!
2. Core React Router v6+ Setup
import { BrowserRouter, Routes, Route, Link, NavLink } from "react-router-dom";
function App() {
return (
<BrowserRouter>
{/* 1. Global Navigation Bar */}
<nav className="navbar">
<NavLink to="/" className={({ isActive }) => isActive ? "nav-link active" : "nav-link"}>
Home
</NavLink>
<NavLink to="/courses" className={({ isActive }) => isActive ? "nav-link active" : "nav-link"}>
Courses
</NavLink>
<NavLink to="/about" className={({ isActive }) => isActive ? "nav-link active" : "nav-link"}>
About
</NavLink>
</nav>
{/* 2. Route Switcher */}
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/courses" element={<CoursesPage />} />
<Route path="/courses/:courseId" element={<CourseDetail />} />
<Route path="*" element={<NotFound404 />} />
</Routes>
</BrowserRouter>
);
}
3. Dynamic Route Parameters & Nested Layouts
1. useParams Hook: Reading URL Segments (/courses/:id)
import { useParams } from "react-router-dom";
function CourseDetail() {
// Reads :courseId from the URL path:
const { courseId } = useParams();
return (
<div className="course-detail-view">
<h2>Viewing Course #{courseId}</h2>
<p>Loaded curriculum content for track: {courseId}</p>
</div>
);
}
2. Nested Routes & Shared Layouts with <Outlet />
// Layout component with persistent Sidebar & dynamic Outlet slot:
import { Outlet } from "react-router-dom";
function DashboardLayout() {
return (
<div className="dashboard-grid">
<aside className="sidebar">
<Link to="/dashboard/analytics">Analytics</Link>
<Link to="/dashboard/settings">Settings</Link>
</aside>
<main className="dashboard-content">
{/* Child route components render inside <Outlet /> */}
<Outlet />
</main>
</div>
);
}
// Router Configuration:
<Route path="/dashboard" element={<DashboardLayout />}>
<Route path="analytics" element={<AnalyticsView />} />
<Route path="settings" element={<SettingsView />} />
</Route>
Analytics Overview Component
4. Hands-On Practice Challenges
Master dynamic route matching, query string parsing, and protected authentication guards. Click "Solve Challenge" to open the code editor!
Challenge 1: Replicate useParams Route Matcher
Write an algorithm matchRoutePath(routePattern, currentUrl) that extracts dynamic URL parameters (e.g., /courses/:trackId/:lessonNum matched against /courses/react/28 yields { trackId: 'react', lessonNum: '28' }).
- Split paths by
/and match segment counts. - Extract segments prefixed with
:into theparamsobject. - Return
{ isMatch: true, params }on match ornullon mismatch.
{ isMatch: true, params: { trackId: "react", lessonNum: "28" } }
matchRoutePath to parse dynamic URL segments.
Challenge 2: useSearchParams Query String Parser
Implement a URL query string parser parseQueryParameters(queryString) that converts query strings like ?q=react&sort=desc into a key-value object.
- Strip leading
?if present. - Split pairs on
&and key/value on=. - Use
decodeURIComponentfor clean string decoding.
{ q: "react+router", filter: "active", sort: "desc" }
parseQueryParameters to decode URL query strings.
Challenge 3: Protected Route Auth Guard Simulator
Implement a route guard guardRouteAccess(userAuth, targetPath) that redirects unauthenticated users attempting to access protected routes (/dashboard, /admin) to /login.
- If protected and not logged in, redirect to
/login?redirect=<path>. - If admin route and role is not admin, redirect to
/unauthorized. - Otherwise return
{ allow: true, render: targetPath }.
Guest: { allow: false, redirect: "/login?redirect=%2Fdashboard%2Fanalytics" } | Admin: { allow: true, render: "/admin/settings" }