React Router
Project 4 used four pieces of React Router with a quick primer to get a search page and a detail page working. This chapter covers routing properly — including the two pieces that primer left out entirely: programmatic navigation, and sharing a layout (like a persistent sidebar or header) across several routes.
The Setup, Recapped
BrowserRouter wraps the whole app once, near the top. Routes looks through its Route children for the one whose path matches the current URL, and renders only that one's element.
Link vs NavLink
Both navigate without a full page reload, exactly like Project 4's Link. NavLink is specifically for navigation menus — it knows whether its own to matches the current URL, and exposes that as isActive inside a function passed to className (or style), making "highlight the current page in the nav" straightforward without manually comparing the URL yourself.
useParams and useNavigate
useParams() was already used in Project 4 to read a dynamic URL segment (/product/:id → { id }). useNavigate() is new here — it returns a function for navigating programmatically, from inside an event handler or effect, rather than from a Link the user clicks. This is the right tool for redirecting after a form submits, after a delete completes, or after a login succeeds.
Nested Routes and a Shared Layout
Nesting Route elements means the parent's element (DashboardLayout, with its sidebar) renders for every URL starting with /dashboard, while <Outlet /> marks exactly where the matching child route's content should appear inside it. Visiting /dashboard/profile renders DashboardLayout with ProfilePage dropped into the Outlet — the sidebar never unmounts or re-renders just because the inner page changed, which is exactly the composition pattern (children/Outlet as a flexible slot) from Fundamentals Chapter 9, applied to routing.
A Catch-All "Not Found" Route
A Route with path="*", placed last among the route definitions, matches any URL that didn't match an earlier, more specific route — the standard way to show a friendly 404 page instead of a blank screen for a mistyped or stale URL.
<a href="/about"> instead of <Link to="/about"> triggers a real full-page browser navigation — reloading the entire app from scratch, losing any in-memory state (cart contents, form data, anything not in localStorage), exactly the cost React Router exists to avoid. Link/NavLink intercept the click and update the URL without a reload; a plain anchor tag never does.
Coding Challenges
Build a 3-page app (Home, About, Contact) with a nav bar using NavLink for each, styling the currently active link differently from the others.
📄 View solutionBuild a hardcoded list of products with Link to /product/:id for each, and a ProductDetailPage that reads the id via useParams and shows the matching product's details.
📄 View solutionBuild a layout route with a persistent sidebar (using Outlet) wrapping two nested child pages, plus a catch-all "*" route rendering a NotFoundPage for any unmatched URL.
📄 View solutionChapter 5 Quick Reference
- BrowserRouter wraps the app; Routes/Route map a path to an element
- Link — basic navigation; NavLink — adds active-state awareness for nav menus
- useParams() — reads dynamic URL segments; useNavigate() — navigates programmatically
- Nested routes + <Outlet /> — a shared layout (sidebar, header) wrapping several child pages
- path="*", placed last — catches any URL nothing else matched, for a 404 page
- Always use
Link/NavLink, never a plain<a href>, for in-app navigation - Next chapter: fetching data — proper loading/error patterns beyond the basics from Fundamentals Ch 8