MENU
<Route>
The Route component is perhaps the most important component in React Router to understand and learn to use well. Its most basic responsibility is to render some UI when its path matches the current URL. A <Route> must be rendered inside a <Routes> (or configured as a data-router route object); it no longer does anything useful on its own.
Attributes:
path: string
The URL path to match. Dynamic segments start with a colon (e.g. :id), and a trailing /* matches any remaining characters (a "splat"). A segment can be made optional by suffixing it with a question mark, e.g. :id?. Regex constraint groups on a segment (e.g. the old :id(\d+) syntax) are no longer supported in path patterns – validate the parameter's format in your own code instead. A single <Route> also no longer accepts an array of paths; render one <Route> per pattern instead.
index: bool
Marks the route as the default child to render at the parent route's own URL, with no additional path segment of its own. Used heavily with nested routes (see below).
caseSensitive: bool
If true, "/one" no longer matches "/One". Defaults to false. (This attribute used to be called "sensitive".)
The old "exact" and "strict" boolean attributes are gone entirely – matching is exact by default now, which is exactly why the component that picks a single best match was renamed from <Switch> to <Routes>. A per-Route "location" override is also gone; pass "location" to the surrounding <Routes> instead if you need to match against a custom location.
There is only one way left to render with <Route>: the element attribute, holding a JSX element (not a component reference). A "Component" attribute taking a bare component reference also still exists as a lighter-weight alternative, but "element" is the attribute you'll see recommended almost everywhere. Whichever you use, the rendered component receives no special props at all – call useParams(), useLocation(), or useNavigate() yourself to read what the old match/location/history route props used to hand you.
<Route path="/users/:id" caseSensitive>
<User />
</Route><Route element>
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter as Router, Routes, Route, useParams } from "react-router";
// Params are read with the useParams() hook instead of a "match" prop
function User() {
let { username } = useParams();
return <h1>Hello {username}!</h1>;
}
ReactDOM.createRoot(node).render(
<Router>
<Routes>
<Route path="/user/:username" element={<User />} />
</Routes>
</Router>
);<Route> nesting and <Outlet>
The old "render"/"children" function attributes, once used to wrap a matched route in extra markup (for example to fade it in, or to keep rendering something whether or not the route matched), no longer exist on <Route>. The replacement for "wrapping" a set of routes in shared markup is nesting: a parent <Route> with its own "element" renders an <Outlet /> wherever it wants its matched child route to appear.
import { Routes, Route, Outlet } from "react-router";
// FadeIn wraps whichever child route element ends up matching
function FadingLayout() {
return (
<FadeIn>
<Outlet />
</FadeIn>
);
}
function App() {
return (
<Routes>
<Route element={<FadingLayout />}>
<Route path="/cool" element={<Something />} />
</Route>
</Routes>
);
}Highlighting a link only while its own route is active used to be done by giving <Route> a "children" function and checking whether "match" came back non-null. That's now <NavLink>'s job (see <NavLink>), or, for full manual control, the useMatch() hook (see Custom Link).