Routing
|
This section documents React 19.x for the web, using function components and Hooks throughout (class components appear only where React still requires them, such as error boundaries). React Native is out of scope and gets only a pointer. The React 19 additions follow the current official React documentation. This content was generated with the assistance of AI and should be verified against react.dev before being relied on in production, since React APIs continue to evolve between releases. This section’s bibliography lists the reference material consulted while preparing these pages. |
React itself has no router. Client-side routing — mapping the URL to which components render, without a full page reload — is provided by a library. This page is a short orientation; follow the links for the full reference.
The options
-
React Router — the most widely used; its data APIs add loaders, actions, and pending UI. Also runs as a full framework (formerly Remix).
-
TanStack Router — type-safe routes and search params, first-class data loading.
-
Framework routers — Next.js App Router (file-system routes, Server Components; see Next.js routing fundamentals), Expo Router for React Native (see Navigation for mobile navigation in depth). If you use a framework, use its router.
Library router vs framework router
A library router is a package you add to a client-rendered app, and you wire data loading, bundling and rendering yourself. A framework router is part of a framework that owns the build, the server and the route conventions. React Router spans both: its three modes are additive.
| Router | Route definition | Data loading | Code splitting | SSR | Nested layouts |
|---|---|---|---|---|---|
React Router — declarative mode |
JSX ( |
None built in; bring your own (Effects, TanStack Query) |
Manual ( |
Manual, with |
Yes, |
React Router — data mode |
Route objects passed to |
|
Route |
Manual, with |
Yes, nested |
React Router — framework mode |
|
Route module |
Automatic, per route |
SPA, SSR and static pre-rendering strategies |
Yes |
Code-based routes or file-based routes (generated route tree), with type-safe params and search params |
Route |
Automatic ( |
Documented, but marked experimental while TanStack Start is not stable |
Yes |
|
File-system: folders with |
|
Automatic, per route segment |
Yes: static, dynamic and streaming rendering by default |
Yes, |
|
File-system: files under |
Data loaders (web) |
Async routes on web (stable and on by default from SDK 58; experimental on native) |
Static rendering and server rendering on web (server rendering stable from SDK 58) |
Yes, |
With React Router, the mode is chosen by the top-level API you use (BrowserRouter, createBrowserRouter, or
the Vite plugin), and every example below imports from the react-router package. Since React Router 7 the former react-router-dom package is merged into react-router; react-router-dom is only a thin re-export of it (its latest release is still 7.x), and the current react-router major version is 8.
Minimal examples (React Router)
Declaring routes, including a nested route and a lazy one:
import { createBrowserRouter, RouterProvider } from 'react-router';
const router = createBrowserRouter([
{
path: '/',
element: <Layout />,
children: [
{ index: true, element: <Home /> },
{ path: 'products/:id', element: <Product /> },
{ path: 'reports', lazy: () => import('./routes/reports.jsx') },
],
},
]);
<RouterProvider router={router} />;
Route params and query params:
import { useParams, useSearchParams } from 'react-router';
function Product() {
const { id } = useParams(); // "products/:id"
const [searchParams] = useSearchParams();
const tab = searchParams.get('tab') ?? 'overview'; // ?tab=specs
return <h1>Product {id} — {tab}</h1>;
}
Links and programmatic navigation:
import { Link, NavLink, useNavigate } from 'react-router';
<Link to="/products/42">View</Link>
<NavLink to="/reports" className={({ isActive }) => (isActive ? 'on' : undefined)}>
Reports
</NavLink>;
function SaveButton() {
const navigate = useNavigate();
return <button onClick={() => navigate('/products/42')}>Go</button>;
}
Lazy routes pair with code splitting: each route’s component is its own chunk, downloaded on first visit. For everything else — data loading, nested layouts, error elements, scroll restoration — see reactrouter.com, tanstack.com/router, or the Next.js docs (and Next.js routing fundamentals in this reference).