šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

SPA Navigation in React: Web Development

Master React Router. Learn to build dynamic routes with parameters, implement seamless navigation with Links and NavLinks, and manage application flow programmatically with the navigate hook.

⚔ Total XP: 0|šŸ’» react XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

Core logic.

Quick Quiz //

What is the primary danger of ignoring this concept?


šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

React apps that feel like multi-page websites, with distinct URLs for each view, rely on React Router to swap components in and out without ever reloading the page. This lesson covers wiring up BrowserRouter, defining dynamic routes, and navigating both declaratively with Link and programmatically with useNavigate.

1What is an SPA?

In a traditional multi-page website, every link click sends a request to the server for a brand-new HTML document, producing a visible flash and a full reload. A Single Page Application (SPA) avoids this entirely: the browser loads a single HTML file once, and from then on JavaScript swaps the visible content in and out to simulate moving between pages.

React Router is the library that makes this illusion work: it watches the browser's URL and decides, without ever triggering a server round-trip, which components should be mounted on screen at any given moment.

āœ•
—
+
// React Router: Navigation without reloads
localhost:3000

Zero Reloads

Instant transitions

2React Router

React itself ships with no built-in routing solution — the de facto standard library for this job is react-router-dom. It works by watching the browser's current URL and using that value to decide which of your components should be rendered at any given moment, all without a full page reload.

Installing it (npm install react-router-dom) gives you the building blocks — BrowserRouter, Routes, Route, Link, and hooks like useParams and useNavigate — needed to wire an entire multi-page-feeling app on top of a single HTML document.

āœ•
—
+
<Route path='/about' element={<About />} />
localhost:3000

The Traffic Cop

Mapping URLs to Components

3The BrowserRouter

To make React Router work anywhere in your app, you wrap the entire component tree in a <BrowserRouter> at the root, typically right around <App />. This component plugs into the browser's History API, which is what lets it detect URL changes and keep the back and forward buttons behaving correctly.

Without this wrapper, none of React Router's other components — Routes, Route, Link, or any of its navigation hooks — have access to the routing context they need to function.

āœ•
—
+
import { Link } from 'react-router-dom';

<Link to='/contact'>Contact Us</Link>
localhost:3000

The Foundation

Wrap your root component.

4Defining Routes

Route definitions live inside a <Routes> container, with each individual <Route> mapping one URL to one component. A Route takes two key props: path, the URL string to match, and element, the JSX that should render when that path is active.

React Router checks the current URL against each Route's path and renders only the matching element — so <Route path="/about" element={<About />} /> shows the About component only when the browser is at /about.

āœ•
—
+
<Route path='/user/:id' element={<Profile />} />
localhost:3000

Route Mapping

path āž” element

5Navigation: The Link Component

Standard <a href> tags should never be used for in-app navigation in a React Router application, because clicking one tells the browser to fetch a whole new HTML document — exactly the full-page reload an SPA is built to avoid. React Router's <Link> component replaces the anchor tag entirely.

A <Link to="/about"> intercepts the click, updates the URL via the History API, and lets React swap the rendered components instantly, with no reload and no white flash.

āœ•
—
+
const { id } = useParams();
// id = '123' if URL is /user/123
localhost:3000

Ban the Anchor Tag

Link prevents the reload.

6Dynamic Route Parameters

Real apps need URLs that vary, like /users/1 or /users/42, without writing a separate Route for every possible ID. React Router supports this with dynamic segments: prefixing a piece of the path with a colon, as in path="/users/:userId", tells the router that segment is a variable rather than a literal string.

Any value in that position of the URL — 1, bob, 99 — will match the route, and the actual matched value becomes available to the rendered component.

āœ•
—
+
const navigate = useNavigate();

const onLogin = () => {
  navigate('/dashboard');
};
localhost:3000

Dynamic Segments

Using the colon :

7Extracting Parameters

Once a dynamic route like /users/:userId matches, the rendered component still needs to know the actual value that was in the URL — for example, to fetch that specific user from an API. React Router's useParams hook provides exactly that.

Calling const { userId } = useParams() inside the matched component returns an object keyed by the dynamic segment names defined in the route, so visiting /users/42 gives you userId === '42' to use in your logic.

āœ•
—
+
<Route path='settings' element={<Settings />}>
  <Route path='profile' element={<Profile />} />
</Route>
localhost:3000

useParams

Extracting URL variables

8Programmatic Navigation

Not every navigation happens because a user clicked a <Link> — sometimes you need to redirect from inside your own logic, like after a login form successfully submits. React Router's useNavigate hook is built for this.

Calling const navigate = useNavigate() gives you a function you can call anywhere in your component, such as navigate('/dashboard') after an async API call resolves, to programmatically change the URL and trigger React Router to render the new matching route.

āœ•
—
+
/* Router Lab: Multi-Page SPA Rendered */
localhost:3000

Imperative Routing

Navigating from JS logic.

9Nested Routes

Routes can be nested inside other routes, which is the pattern behind layouts like a dashboard where a sidebar stays fixed but the central content changes with the URL. A parent <Route> wraps child <Route> elements, and the parent's component renders an <Outlet /> at the exact spot where the matching child should appear.

So visiting /dashboard/billing keeps the DashboardLayout (and its sidebar) mounted while swapping only the <Outlet /> content for the Billing component.

āœ•
—
+
<Route path='*' element={<NotFound />} />
localhost:3000

The Outlet

Where children render

10Catch-all Routes (404)

A catch-all 404 route is created by placing a <Route> with path="*" at the very bottom of your <Routes> list. The asterisk works as a wildcard that matches any URL that wasn't already matched by a route defined above it.

Because React Router checks routes in order and stops at the first match, this wildcard route only ever renders when nothing else did, making it the natural place to render a NotFound component for unrecognized URLs.

āœ•
—
+
<NavLink className={({ isActive }) => ...} />
localhost:3000

Handling 404s

path="*"

11NavLink (Active states)

<NavLink> is React Router's alternative to <Link> built specifically for navigation menus where you want to visually highlight whichever link corresponds to the current page. It behaves identically to <Link> for navigation purposes, but it also passes an isActive boolean into a function you provide for its className or style prop.

That means you can write className={({ isActive }) => isActive ? 'active-link' : ''} and have the active menu item style itself automatically as the URL changes.

āœ•
—
+
// Data Loader Pattern
localhost:3000

Active States

Automatic highlighting.

12Mastery Achieved

With BrowserRouter, Routes, dynamic parameters via useParams, programmatic redirects via useNavigate, nested layouts with Outlet, and a wildcard catch-all for 404s, you now have everything needed to build a complete, seamless single-page application. The URL changes, but the page never reloads.

The next step is connecting these routed views to real data, so the components rendered at each URL can fetch and display information from an API.

āœ•
—
+
/* Next: API Integration (Fetching) */
localhost:3000

Navigation Mastered āœ“

13Step-by-Step Breakdown

What is an SPA?. Welcome to SPA Navigation. In traditional websites, clicking a link causes the browser to fetch a completely new HTML document from the server, resulting in a white flash and a full page reload. A Single Page Application (SPA) works differently: it loads exactly ONE HTML file, and JavaScript dynamically swaps out the content to simulate moving between pages.

React Router. React itself doesn't have a built-in router. The industry standard library for this is react-router-dom. It tracks the browser's URL and determines which React components should be visible on the screen at any given time.

The BrowserRouter. To use React Router, you must wrap your entire application in a <BrowserRouter>. This component connects your app to the browser's History API, allowing it to listen for URL changes and update the back/forward buttons correctly.

Defining Routes. Inside your app, you define a <Routes> container, and inside that, individual <Route> components. A Route takes two main props: path (the URL string) and element (the JSX to render when the URL matches).

Which prop on the <Route> component is used to specify the component that should be rendered?

  • →component
  • →element

Navigation: The Link Component. To move between pages, you must NEVER use standard <a href> tags. A standard link tells the browser to fetch a new document, breaking the SPA and reloading the whole app. Instead, you use React Router's <Link> component. It intercepts the click and updates the URL instantly.

What prop does the <Link> component use to define the destination URL?

  • →href
  • →to

Dynamic Route Parameters. Often, you need URLs that are dynamic, like /users/1 or /users/42. You can define a dynamic parameter in your route path by prefixing a segment with a colon (:). This tells the router that this segment is a variable.

Extracting Parameters. Once you navigate to a dynamic route, the rendered component needs to know what that dynamic value is (e.g., to fetch the correct user from an API). You extract this value using the useParams hook provided by React Router.

Programmatic Navigation. Sometimes you need to change the page automatically from your logic, not because the user clicked a <Link>. For example, redirecting after a successful login or form submission. For this, we use the useNavigate hook.

Nested Routes. You can nest routes inside other routes! This is perfect for complex layouts like a Dashboard where a sidebar remains constant, but the central content changes based on the URL (e.g., /dashboard/settings vs /dashboard/billing). You render an <Outlet> component in the parent where the child routes should appear.

Which hook do you use to navigate from inside a component's logic (like a setTimeout callback)?

  • →useParams
  • →useNavigate

Catch-all Routes (404). To handle "404 Not Found" errors, you place a <Route> at the very bottom of your routing list with the path *. The asterisk acts as a wildcard. If none of the routes above it match the URL, this wildcard route will catch it.

NavLink (Active states). For navigation menus, you often want to highlight the link that corresponds to the page you are currently on. React Router provides <NavLink> which is just like <Link>, but it automatically passes an isActive boolean to its class/style props so you can style it dynamically.

Mastery Achieved. Router mastery achieved! You now know how to build a seamless, fast SPA with dynamic parameters, programmatic navigation, and nested layouts. Next up: integrating external data with API fetching!

Level Up šŸš€

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1Manage Focus on Route Changes

Because React Router swaps components without a full page reload, the browser doesn't automatically reset focus or announce the new view to screen reader users the way a traditional page load does — move focus to the new page's heading (or a dedicated announcement region) after each navigation.

2Use NavLink's aria-current for Active Navigation Items

NavLink can apply `aria-current="page"` to the link matching the current route, giving screen reader users an explicit signal of which navigation item represents the page they're on, beyond just a visual style difference.

SEO Implications

  • 1

    Client-Side Routes Need Server-Side Awareness for Direct Loads

    If a user (or a search engine crawler) requests a deep URL like /users/42 directly, your server must be configured to serve the same index.html for all routes, or the request 404s before React Router ever gets a chance to render the matching component.

  • 2

    Each Route Should Set Its Own Title and Meta Tags

    Because an SPA loads one HTML document, the page title and meta description won't change automatically as users navigate — each routed component needs to update these itself (or via a framework's head-management APIs) so search engines and browser tabs reflect the current view.

Best Practices

Always Place the Wildcard Route Last

Since React Router matches routes in order and stops at the first match, a catch-all path="*" route placed before more specific routes would intercept every URL — it must always be the final entry inside <Routes>.

Never Use <a href> for Internal Navigation

A plain anchor tag forces a full document reload, which reinitializes your entire React app and discards any in-memory state; use <Link> or <NavLink> for every internal link so the SPA's single-load model stays intact.

Frequent Bugs

THE BUG

Clicking an internal link causes a full page reload and a visible flash instead of an instant transition.

THE FIX

A standard <a href> tag was used instead of React Router's <Link to="...">, which is the only component that intercepts the click and updates the URL through the History API without requesting a new document.

THE BUG

useParams() returns undefined for a value that should be present in the URL.

THE FIX

The dynamic segment name used in useParams() doesn't match the name defined in the route's path — the destructured key must exactly match the colon-prefixed segment, e.g. path="/users/:userId" requires const { userId } = useParams(), not const { id } = useParams().

Real-World Examples

Protected Dashboard With Nested Routes

A dashboard layout renders a persistent sidebar and header, with an <Outlet /> that swaps between Billing, Settings, and Profile sub-views as the user clicks between /dashboard/billing and /dashboard/settings, all without remounting the layout.

<Route path='/dashboard' element={<DashboardLayout />}>
  <Route path='billing' element={<Billing />} />
  <Route path='settings' element={<Settings />} />
</Route>

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Mutating State Directly

// Wrong const [user, setUser] = useState({ name: 'Alice' }); user.name = 'Bob'; // React won't re-render // Correct setUser({ ...user, name: 'Bob' });

The Solution //

Never mutate a state variable directly (e.g., state.count = 1). Always use the setter function provided by useState to ensure the component re-renders.

The Error //

Missing 'key' prop in lists

// Wrong {items.map(item => <li>{item.name}</li>)} // Correct {items.map(item => <li key={item.id}>{item.name}</li>)}

The Solution //

When rendering a list of elements using .map(), always provide a unique 'key' prop to the outermost element to help React identify which items have changed.

Lesson Glossary

[01]SPA

Single Page Application. A web app that loads a single HTML page and dynamically updates content as the user interacts.

Code Preview
No Reloads

[02]Router

The system that synchronizes the UI with the URL.

Code Preview
<BrowserRouter>

[03]Route

A mapping between a URL path and a specific React component.

Code Preview
<Route path='/...' />

[04]Link

The React component used to navigate between routes without reloading the browser.

Code Preview
<Link to='/...' />

[05]useParams

A hook that returns an object of key/value pairs of URL parameters.

Code Preview
const { id } = useParams()

[06]useNavigate

A hook that returns a function which lets you navigate programmatically.

Code Preview
navigate('/home')

Continue Learning