React Router DOM Route Component (With Examples)

The Route component in React Router (react-router-dom) maps a URL path to the element to render: <Route path="/about" element={<About />} />. Routes live inside <Routes>, which renders the best match for the current URL, and the whole app is wrapped in <BrowserRouter>. This guide covers the React Router DOM Route component from the first route to URL parameters, nested routes with Outlet, index and catch-all (404) routes, redirects, navigation from code and protected routes.

Every example was built with React 19.3.0, react-router-dom 7.18.4 and Vite 8.3.0 (npx vite build) and opened in Microsoft Edge; links were clicked with real mouse events and the outputs are the browser console messages. Reference: Routing in the React Router documentation.

Install React Router

npm install react-router-dom

React Router v7 needs React 18 or later. (In v7 you can also import the same components from react-router; react-router-dom re-exports them.)

Basic Route components

Each Route has a path and an element. Link changes the URL without reloading the page:

import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function Home() { return <h2>Home</h2>; }
function About() { return <h2>About us</h2>; }
function Contact() { return <h2>Contact: hello@example.com</h2>; }

export default function App() {
  return (
    <BrowserRouter>
      <nav style={{ display: "flex", gap: 16 }}>
        <Link to="/">Home</Link>
        <Link to="/about" id="about-link">About</Link>
        <Link to="/contact">Contact</Link>
      </nav>

      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
      </Routes>
    </BrowserRouter>
  );
}
React Router app in Microsoft Edge showing the About us page after clicking the About link rendered by a Route component
After clicking “About”, the URL is /about and only the About route renders.
Route propMeaning
pathURL pattern, e.g. /about, /products/:id, *
elementWhat to render when the path matches
indexDefault child of a parent route (no path of its own)
caseSensitiveMatch the path case-sensitively (off by default)
childrenNested <Route> elements

Route parameters with useParams

A segment starting with : is a parameter. Read it in the component with useParams(); the value is always a string:

import { BrowserRouter, Routes, Route, Link, useParams, useLocation } from "react-router-dom";

const products = { 101: "Laptop Stand", 102: "USB-C Hub" };

function Product() {
  const { id } = useParams();                   // the :id part of the URL
  const location = useLocation();
  console.log("route matched:", location.pathname, "id =", id);
  return <h2>{products[id] ?? "Unknown product"} (id {id})</h2>;
}

export default function App() {
  return (
    <BrowserRouter>
      <Link to="/products/101" id="p101">Laptop Stand</Link> | <Link to="/products/102" id="p102">USB-C Hub</Link>
      <Routes>
        <Route path="/products/:id" element={<Product />} />
      </Routes>
    </BrowserRouter>
  );
}

Console output (page opened at /products/101, then both links clicked):

route matched: /products/101 id = 101
route matched: /products/101 id = 101
route matched: /products/102 id = 102
React Router page in Edge showing USB-C Hub (id 102) rendered from the :id route parameter read with useParams
One route, /products/:id, renders every product.

Nested routes, index routes and Outlet

Put Route elements inside another Route to share a layout. Child paths are relative to the parent, the layout renders the matched child in <Outlet />, and the index route is shown at the parent’s own URL:

import { BrowserRouter, Routes, Route, NavLink, Outlet } from "react-router-dom";

function DashboardLayout() {
  const style = ({ isActive }) => ({ fontWeight: isActive ? "bold" : "normal", marginRight: 16 });
  return (
    <div>
      <h2>Dashboard</h2>
      <NavLink to="/dashboard" end style={style}>Overview</NavLink>
      <NavLink to="/dashboard/orders" style={style} id="orders">Orders</NavLink>
      <NavLink to="/dashboard/settings" style={style}>Settings</NavLink>
      <div style={{ border: "1px dashed #999", padding: 8, marginTop: 8 }}>
        <Outlet />                                        {/* child routes render here */}
      </div>
    </div>
  );
}

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/dashboard" element={<DashboardLayout />}>
          <Route index element={<p>3 new orders today.</p>} />            {/* /dashboard */}
          <Route path="orders" element={<p>Order list: #5001, #5002, #5003</p>} />   {/* /dashboard/orders */}
          <Route path="settings" element={<p>Account settings</p>} />
        </Route>
        <Route path="*" element={<p>404: page not found</p>} />
      </Routes>
    </BrowserRouter>
  );
}
React Router dashboard in Edge with nested routes: Orders NavLink in bold and the order list rendered inside the Outlet
At /dashboard/orders the layout stays and the Outlet shows the Orders route; NavLink marks it active.

404 page and redirects

path="*" matches any URL no other route matched, which makes it the 404 page. To redirect, render <Navigate to="..." replace /> as the route’s element:

import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";

function Pricing() {
  console.log("Pricing rendered at", window.location.pathname);
  return <h2>Pricing</h2>;
}

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<h2>Home</h2>} />
        <Route path="/old-pricing" element={<Navigate to="/pricing" replace />} />   {/* redirect */}
        <Route path="/pricing" element={<Pricing />} />
        <Route path="*" element={<h2>404: nothing at {window.location.pathname}</h2>} />  {/* catch-all */}
      </Routes>
    </BrowserRouter>
  );
}
React Router catch-all route in Edge showing 404 nothing at /blog/missing-post for an unknown URL
The page opened at /blog/missing-post falls through to the * route.

Opening /old-pricing in the same app redirects: the console shows Pricing rendered at /pricing. On a real server, make every path return index.html (a “history API fallback”), or refreshing a nested URL returns the server’s own 404.

Navigate from code with useNavigate

After a form submit or login, call navigate(path). navigate(-1) goes back one page:

import { BrowserRouter, Routes, Route, useNavigate } from "react-router-dom";
import { useState } from "react";

function Login() {
  const navigate = useNavigate();
  const [name, setName] = useState("");
  return (
    <form onSubmit={(e) => { e.preventDefault(); navigate(`/welcome/${name}`); }}>
      <input id="name" placeholder="Your name" value={name} onChange={(e) => setName(e.target.value)} />
      <button id="go">Log in</button>
    </form>
  );
}

function Welcome() {
  const navigate = useNavigate();
  console.log("now at", window.location.pathname);
  return <p>Welcome! <button onClick={() => navigate(-1)}>Back</button></p>;
}

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Login />} />
        <Route path="/welcome/:name" element={<Welcome />} />
      </Routes>
    </BrowserRouter>
  );
}

Console output after typing Priya and clicking “Log in”:

now at /welcome/Priya

Protected routes

Wrap the element of a private route in a small component that checks the user and redirects guests:

import { BrowserRouter, Routes, Route, Navigate, Link } from "react-router-dom";

const user = null;                                     // not logged in

function RequireAuth({ children }) {
  if (!user) return <Navigate to="/login" replace />;   // send guests to the login page
  return children;
}

export default function App() {
  return (
    <BrowserRouter>
      <Link to="/account" id="account">My account</Link>
      <Routes>
        <Route path="/" element={<h2>Home</h2>} />
        <Route path="/login" element={<h2>Please log in</h2>} />
        <Route path="/account" element={<RequireAuth><h2>Account details</h2></RequireAuth>} />
      </Routes>
    </BrowserRouter>
  );
}
React Router protected route in Edge redirecting a guest from My account to the Please log in page
Clicking “My account” as a guest ends on /login.

Route in React Router v5 vs v6/v7

v5v6 and v7
<Switch><Routes>
component={About} or renderelement={<About />}
exactNot needed: routes match exactly by default
<Redirect><Navigate>
useHistory()useNavigate()
match.paramsuseParams()

Related React tutorials on this site:

Frequently asked questions

What is the Route component in React Router?

It maps a URL path to an element: <Route path="/about" element={<About />} />. Routes are placed inside <Routes>.

How do I get URL parameters in a route?

Define the parameter with a colon (path="/users/:id") and read it with const { id } = useParams().

How do I make a 404 route?

Add <Route path="*" element={<NotFound />} /> as the last route.

How do I redirect in React Router v6 and v7?

Render <Navigate to="/new-path" replace />, or call navigate("/new-path") from useNavigate().

What replaced Switch and the component prop?

Routes replaced Switch, and the element prop replaced component and render.

How do nested routes work?

Put child Routes inside a parent route and render <Outlet /> in the parent’s element; child paths are relative.