React Router v7 From Scratch: 7 Patterns Every SPA Needs
Every React SPA needs routing, and the gap between a working setup and one that loads fast, handles edge cases, and stays maintainable comes down to these seven patterns. Getting lazy loading, nested layouts, and navigation right early prevents the most common performance and UX regressions.
Frontend routing replaces the server's traditional URL-to-HTML mapping with JavaScript-driven DOM swaps, eliminating white-screen flashes between pages. This walkthrough builds a full React Router v7 system step by step, starting from the core trio of HashRouter, Routes, and Route, then layering on lazy loading with React.lazy and Suspense to cut initial bundle sizes by over 80%.
Nested routes use the Outlet component as a content slot, letting parent routes supply shared chrome like sidebars while child routes own their specific UI. Dynamic segments captured via useParams feed URL values directly into components, and useNavigate handles programmatic jumps for form submissions or auth redirects without triggering a full-page refresh. A wildcard path="*" route catches all unmatched URLs, but only when placed last in the Routes tree.
The guide closes with a layout decision heuristic: if a piece of UI would look wrong on one child page, it belongs in that child, not the parent. The same lifting principle that governs React state applies to route layouts.
The layout decision heuristic—'would this UI look wrong on that child page?'—is a practical rule that mirrors React's state-lifting principle but applies it to component structure, which many routing tutorials skip.
Framing lazy loading as an 80% bundle reduction rather than a generic performance tip makes the tradeoff concrete: the user pays only for the page they actually visit.
The warning against <a> tags in SPAs addresses a persistent beginner mistake that survives because it looks correct in the DOM but silently destroys application state.