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>
);
}
/about and only the About route renders.| Route prop | Meaning |
|---|---|
path | URL pattern, e.g. /about, /products/:id, * |
element | What to render when the path matches |
index | Default child of a parent route (no path of its own) |
caseSensitive | Match the path case-sensitively (off by default) |
| children | Nested <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
/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>
);
}
/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>
);
}
/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>
);
}
/login.Route in React Router v5 vs v6/v7
| v5 | v6 and v7 |
|---|---|
<Switch> | <Routes> |
component={About} or render | element={<About />} |
exact | Not needed: routes match exactly by default |
<Redirect> | <Navigate> |
useHistory() | useNavigate() |
match.params | useParams() |
Related React tutorials on this site:
- Pass props to a component in React
- Use React components with children
- Open a React component in a new tab
- Set up a React environment
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.
Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn