šŸš€ 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 ///

React Router DOM | React Tutorial

Learn about React Router DOM in this comprehensive React tutorial for frontend web development. Learn to manage URL state, define dynamic routes, and handle navigation programmatically using the latest v6 syntax.

⚔ 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-router-dom is what turns a React app into a true single-page application, swapping components in and out as the URL changes instead of reloading the page. This lesson covers BrowserRouter, defining routes, safe client-side links, dynamic URL parameters, and navigating programmatically.

1The Single Page App

In a traditional website, clicking a link makes the browser request an entirely new HTML document from the server, causing a visible flash as the page reloads. A React Single Page Application (SPA) only ever loads one HTML file — JavaScript then dynamically swaps which components are visible as the user navigates.

This is exactly what react-router-dom manages: keeping the visible components in sync with the URL, without ever triggering a full page reload, which is what makes navigation in an SPA feel instantaneous.

āœ•
—
+
// Example
console.log("Running React SPA Router...");
localhost:3000

The SPA Paradigm

One HTML page, infinite dynamic views.

2BrowserRouter Provider

To enable routing at all, the entire component tree needs to be wrapped in a <BrowserRouter> component. Under the hood, BrowserRouter uses the HTML5 History API to keep React's internal notion of the current location in sync with the browser's actual URL bar.

This is also what makes the browser's back and forward buttons work correctly inside an SPA — without this provider, none of React Router's other components or hooks have any routing context to work with.

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

function App() {
  return (
    <BrowserRouter>
      <AppContent />
    </BrowserRouter>
  );
}
localhost:3000
Top Level: BrowserRouter wraps everything.

3Defining Routes

With the provider in place, actual paths get defined using a <Routes> container holding individual <Route> components. Each <Route> takes a path string describing what the URL should look like, and an element prop containing the JSX to render when that path matches.

A typical app lists several of these together, like <Route path="/" element={<Home />} /> and <Route path="/about" element={<About />} />, so <Routes> can render whichever one fits the current URL.

āœ•
—
+
import { Routes, Route } from 'react-router-dom';

<Routes>
  <Route path='/' element={<Home />} />
  <Route path='/about' element={<About />} />
</Routes>
localhost:3000

Mapping URLs to Components

path āž”ļø element

4Client-Side Links

Standard HTML <a> tags must not be used for internal navigation, since they trigger a full page reload and destroy all React state. Instead, import <Link> from react-router-dom — it renders as a real <a> tag in the DOM (good for SEO and accessibility), but overrides the click event to perform fast client-side routing instead.

A typical navbar looks like <Link to="/">Home</Link> and <Link to="/about">About</Link> — visually identical to anchor tags, but without the destructive full-page reload.

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

<nav>
  <Link to='/'>Home</Link>
  <Link to='/about'>About</Link>
</nav>
localhost:3000

Never use <a href>

For internal app links.

5NavLink for Menus

Navigation menus often need to visually highlight whichever link corresponds to the current page. <NavLink> is a special version of <Link> that knows whether it's currently the active route.

Passing a function to its className (or style) prop, like ({ isActive }) => isActive ? 'active-link' : '', lets React Router apply conditional styling automatically based on whether that link's to matches the current URL.

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

Active Styling

Use NavLink for navbars

6Catch-All 404 Pages

When a user visits a URL that doesn't match any defined route, the app needs a "Not Found" page. React Router makes this simple: add a <Route> at the very bottom of the <Routes> list with path="*", the wildcard.

Because <Routes> evaluates matches by specificity and * is the least specific possible pattern, this catch-all route only renders when no other, more specific route matched the current URL.

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

404

Page Not Found

7Dynamic URL Parameters

Routes that share a common shape, like a user profile page, don't need a separate route written out for every possible user. Prefixing a path segment with a colon, like /users/:id, tells React Router that segment is a dynamic parameter that should match any value.

A route can even have multiple dynamic segments, such as /store/:category/:item, letting a single <Route> definition handle an entire family of URLs.

āœ•
—
+
function UserProfile() {
  const { id } = useParams();
  return <h2>User: {id}</h2>;
}
localhost:3000

Dynamic Paths

/resource/:variable

8The useParams Hook

Once a dynamic route matches, the actual value from the URL still needs to be read inside the rendered component — that's what the useParams() hook is for. It returns an object containing every dynamic parameter defined in the matched route's path.

For a route defined as /users/:id, calling const { id } = useParams() inside the rendered component extracts whatever value was actually present in the URL, like '123' from /users/123.

āœ•
—
+
const navigate = useNavigate();
const goHome = () => navigate('/');
localhost:3000

Extracting Data

useParams()

9Programmatic Navigation

<Link> is great for navigation the user triggers by clicking, but some navigation needs to happen from JavaScript logic itself — redirecting after a login form successfully submits, for example. React Router's useNavigate hook returns a function for exactly this.

Calling navigate('/dashboard') inside an async success handler, after await api.login() resolves, redirects the user immediately without requiring any click at all.

āœ•
—
+
<h1>Routing Master Unlocked!</h1>
localhost:3000

10Step-by-Step Breakdown

The Single Page App. Welcome to React Router DOM. In traditional websites, clicking a link causes the browser to make a full network request for a completely new HTML document, causing the screen to flash white. In a React Single Page Application (SPA), we only ever load ONE HTML file. We then use JavaScript to dynamically swap out which React components are currently visible, making navigation feel instantaneous.

BrowserRouter Provider. To enable routing in your application, you must wrap your entire component tree in a <BrowserRouter> component. This provider uses the HTML5 History API under the hood to sync your React state with the browser's URL bar, enabling the back/forward buttons to work seamlessly.

Defining Routes. Once the provider is in place, you define your actual paths using the <Routes> container and individual <Route> components. The <Route> component takes a path string (what the URL should look like) and an element prop containing the JSX you want to render when the URL matches that path.

Which prop on the <Route> component determines which JSX gets rendered when the URL matches?

  • →render
  • →component
  • →element

Client-Side Links. Crucially, you MUST stop using standard HTML <a> tags for internal links. An <a> tag will trigger a full page reload, destroying your React state. Instead, import the <Link> component from React Router. It renders as an <a> tag in the DOM for SEO and accessibility, but it overrides the click event to perform lightning-fast client-side routing.

Which component completely intercepts the browser's default click behavior to allow fast, client-side routing in an SPA?

  • →<a>
  • →<Link>

NavLink for Menus. For navigation menus, you often want to highlight the 'active' link. React Router provides <NavLink>, a special version of <Link> that knows whether or not it is the current active route. It automatically allows you to apply conditional classes or styles based on its active state.

Catch-All 404 Pages. What happens if a user types in a URL that doesn't exist? You need a 'Not Found' page. React Router makes this incredibly easy. Simply create a route at the very bottom of your <Routes> list and set the path to the wildcard asterisk (*). This route will only trigger if no previous routes matched the URL.

Dynamic URL Parameters. Often, you need routes that share a common pattern, like a user profile page. You don't want to write a route for every user. Instead, use Dynamic Segments. By prefixing a path segment with a colon (:), you tell React Router that this portion of the URL is a variable parameter.

If you want a route to match paths like /post/45 or /post/hello-world, how should you define the route path prop?

  • →"/post/$postId"
  • →"/post/:postId"

The useParams Hook. Once the dynamic route is matched, you need to read the actual value out of the URL (e.g., extracting '123' from /users/123). Inside the rendered component, you use the useParams() hook. It returns an object containing all the dynamic parameters defined in your route path.

Programmatic Navigation. Links are great for users clicking around, but sometimes you need to trigger navigation programmatically from your JavaScript logic. For example, redirecting the user AFTER they successfully submit a login form. For this, React Router provides the useNavigate hook.

Which hook should you use if you need to redirect a user to a success page immediately after an API fetch completes?

  • →useLocation
  • →useNavigate

Nested Routes. For complex layouts, React Router supports Nested Routes. Imagine a Dashboard where the sidebar stays the same, but the inner content changes between 'Profile' and 'Settings'. You can place <Route> tags INSIDE other <Route> tags to achieve this powerful layout architecture.

Mastery Achieved. Routing mastery achieved! You now know how to architect a modern React SPA using react-router-dom v6. You can define static and dynamic routes, catch 404 errors, use safe client-side links, and trigger programmatic redirects. You are ready to build multi-page apps!

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)

1Announce Route Changes to Assistive Technology

Because client-side navigation never triggers a full page reload, screen readers won't automatically announce a new page — move focus to the new view's main heading after navigating so assistive technology users know the route changed.

2NavLink's isActive State Should Be Visually and Programmatically Clear

When highlighting the active link in a nav menu with `<NavLink>`, don't rely on color alone — pair the active styling with `aria-current="page"` so assistive technology can also identify the current page.

SEO Implications

  • 1

    Every Route Needs a Real, Crawlable URL

    Because `react-router-dom` handles navigation entirely client-side, make sure each `<Route path>` still corresponds to a distinct URL that can be requested directly and rendered with meaningful content, ideally via server-side rendering.

  • 2

    The Wildcard 404 Route Should Return the Right Status Semantics

    A `path="*"` catch-all route improves UX for bad URLs, but if the app is server-rendered, make sure the actual HTTP response for unmatched routes reflects a 404 status, not a 200, so crawlers don't index broken URLs as valid pages.

Best Practices

Never Use a Plain <a> Tag for Internal Navigation

A native anchor tag forces a full page reload and destroys all in-memory React state; always use `<Link>` or `<NavLink>` for links that stay within the app.

Keep the Wildcard 404 Route Last in the List

Since `path="*"` matches literally any URL, place it as the final `<Route>` inside `<Routes>` so more specific routes are always evaluated and available to match first.

Frequent Bugs

THE BUG

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

THE FIX

The parameter name used in `useParams()` doesn't match the name declared in the route's `path`. If the route is `/users/:id`, the destructured key must be `id`, e.g. `const { id } = useParams()`.

THE BUG

Clicking a navigation link causes the whole app to flash white and lose all state.

THE FIX

The link was written as a plain `<a href="...">` instead of React Router's `<Link to="...">`. Replace it with `<Link>` so the click is intercepted and handled via client-side routing instead of a full page request.

Real-World Examples

Dynamic User Profile Route

An app defines `<Route path="/users/:id" element={<UserProfile />} />` so a single component handles every user's profile page, reading the specific `id` out of the URL with `useParams()` to fetch that user's data.

function UserProfile() {
  const { id } = useParams();
  return <h2>Fetching data for user {id}...</h2>;
}

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]BrowserRouter

Component that provides routing context using the History API.

Code Preview
<BrowserRouter>

[02]Routes

Container for grouping all Route definitions.

Code Preview
<Routes>

[03]Route

Connects a URL path to a specific React component.

Code Preview
<Route />

[04]Link

Component for client-side navigation without page reloads.

Code Preview
<Link to=''>

[05]useParams

Hook to extract dynamic parameters from the URL.

Code Preview
useParams()

[06]useNavigate

Hook for programmatically redirecting the user.

Code Preview
useNavigate()

[07]Catch-all Route

A route with path='*' used for 404 pages.

Code Preview
path='*'

Continue Learning