What is react-router?
The react-router npm package is a declarative routing library for React, allowing you to add navigation functionality to your React applications. It enables you to handle URL routing, match routes to your React components, and manage navigation state in a single-page application (SPA) environment.
What are react-router's main functionalities?
Basic Routing
This code demonstrates how to set up basic routing in a React application using react-router. It includes navigation links and route components that render different components based on the URL path.
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to='/'>Home</Link>
</li>
<li>
<Link to='/about'>About</Link>
</li>
</ul>
</nav>
<Route exact path='/' component={Home} />
<Route path='/about' component={About} />
</div>
</Router>
);
}
function Home() {
return <h2>Home</h2>;
}
function About() {
return <h2>About</h2>;
}
Dynamic Routing
This code snippet shows how to implement dynamic routing with path parameters. The User component will render with the appropriate user ID based on the URL.
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
function App() {
return (
<Router>
<div>
<ul>
<li>
<Link to='/users/1'>User 1</Link>
</li>
<li>
<Link to='/users/2'>User 2</Link>
</li>
</ul>
<Route path='/users/:id' component={User} />
</div>
</Router>
);
}
function User({ match }) {
return <h2>User ID: {match.params.id}</h2>;
}
Nested Routing
Nested routing allows you to create routes within routes. This example shows a Layout component with a nested Dashboard route.
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
function App() {
return (
<Router>
<Route path='/' component={Layout} />
</Router>
);
}
function Layout({ match }) {
return (
<div>
<nav>
<Link to={`${match.url}dashboard`}>Dashboard</Link>
</nav>
<Switch>
<Route path={`${match.path}dashboard`} component={Dashboard} />
</Switch>
</div>
);
}
function Dashboard() {
return <h2>Dashboard</h2>;
}
Protected Routes
Protected routes are used to restrict access to certain parts of your application. This example shows a route that renders a component only if the user is authenticated, otherwise it redirects to a login page.
import { BrowserRouter as Router, Route, Redirect } from 'react-router-dom';
function App() {
return (
<Router>
<Route path='/protected' render={() => (
isAuthenticated() ? (
<ProtectedComponent />
) : (
<Redirect to='/login' />
)
)} />
</Router>
);
}
function isAuthenticated() {
// Authentication logic here
return true;
}
function ProtectedComponent() {
return <h2>Protected</h2>;
}
Other packages similar to react-router
vue-router
Vue-router is the official router for Vue.js. It provides similar functionalities for Vue applications as react-router does for React applications, including nested routes, dynamic segments, and navigation guards. However, it is designed to work seamlessly with Vue's reactivity system.
reach-router
Reach Router is another routing library for React, which aims to be more accessible and simpler to use than react-router. It has a smaller API surface area and focuses on accessibility by managing focus after route transitions. However, as of my knowledge cutoff in 2023, Reach Router has been officially merged with React Router, and its features have been integrated into React Router v6.
v7.2.0
Date: 2025-02-18
What's Changed
Type-safe href
utility
In framework mode, we now provide you with a fully type-safe href
utility to give you all the warm and fuzzy feelings of path auto-completion and param validation for links in your application:
import { href } from "react-router";
export default function Component() {
const link = href("/blog/:slug", { slug: "my-first-post" });
// ^ type-safe! ^ Also type-safe!
return (
<main>
<Link to={href("/products/:id", { id: "asdf" })} />
<NavLink to={href("/:lang?/about", { lang: "en" })} />
</main>
);
}
You'll now get type errors if you pass a path path value or a bad param value:
const badPath = href("/not/a/valid/path");
// ^ Error!
const badParam = href("/blog/:slug", { oops: "bad param" });
// ^ Error!
Prerendering with a SPA Fallback
This release enhances the ability to use a combination of pre-rendered paths alongside other paths that operate in "SPA Mode" when pre-rendering with ssr:false
.
- If you specify
ssr:false
without a prerender
config, this is considered "SPA Mode" and the generated index.html
file will only render down to the root route and will be able to hydrate for any valid application path - If you specify
ssr:false
with a prerender
config but do not include the /
path (i.e., prerender: ['/blog/post']
), then we still generate a "SPA Mode" index.html
file that can hydrate for any path in the application - If you specify
ssr:false
and include the /
path in your prerender
config, the generated index.html
file will be specific to the root index route, so we will now also generate a separate "SPA Mode" file in __spa-fallback.html
that you can serve/hydrate for non-prerendered paths
For more info, see the Pre-rendering docs for more info.
Allow a root loader
in SPA Mode
SPA Mode used to prohibit the use of loaders in all routes so that we could hydrate for any path in the application. However, because the root route is always rendered at build time, we can lift this restriction for the root route.
In order to use your build-time loader data during pre-rendering, we now also expose the loaderData
as an optional prop for the HydrateFallback
component on routes:
- This will be defined so long as the
HydrateFallback
is rendering because children routes are loading - This will be
undefined
if the HydrateFallback
is rendering because the route itself has it's own hydrating clientLoader
- In SPA mode, this will allow you to render loader root data into the SPA Mode HTML file
Minor Changes
react-router
- New type-safe href
utility that guarantees links point to actual paths in your app (#13012)@react-router/dev
- Generate a "SPA fallback" HTML file when pre-rendering the /
route with ssr:false
(#12948)@react-router/dev
- Allow a loader
in the root route in SPA mode because it can be called/server-rendered at build time (#12948)
Route.HydrateFallbackProps
now also receives loaderData
Patch Changes
react-router
- Disable Lazy Route Discovery for all ssr:false
apps and not just "SPA Mode" because there is no runtime server to serve the search-param-configured __manifest
requests (#12894)
- We previously only disabled this for "SPA Mode" but we realized it should apply to all
ssr:false
apps - In those
prerender
scenarios we would pre-render the /__manifest
file but that makes some unnecessary assumptions about the static file server behaviors
react-router
- Don't apply Single Fetch revalidation de-optimization when in SPA mode since there is no server HTTP request (#12948)react-router
- Properly handle revalidations to across a pre-render/SPA boundary (#13021)
- In "hybrid" applications where some routes are pre-rendered and some are served from a SPA fallback, we need to avoid making
.data
requests if the path wasn't pre-rendered because the request will 404 - We don't know all the pre-rendered paths client-side, however:
- All
loader
data in ssr:false
mode is static because it's generated at build time - A route must use a
clientLoader
to do anything dynamic - Therefore, if a route only has a
loader
and not a clientLoader
, we disable revalidation by default because there is no new data to retrieve - We short circuit and skip single fetch
.data
request logic if there are no server loaders with shouldLoad=true
in our single fetch dataStrategy
- This ensures that the route doesn't cause a
.data
request that would 404 after a submission
react-router
- Align dev server behavior with static file server behavior when ssr:false
is set (#12948)
- When no
prerender
config exists, only SSR down to the root HydrateFallback
(SPA Mode) - When a
prerender
config exists but the current path is not pre-rendered, only SSR down to the root HydrateFallback
(SPA Fallback) - Return a 404 on
.data
requests to non-pre-rendered paths
react-router
- Improve prefetch performance of CSS side effects in framework mode (#12889)react-router
- Properly handle interrupted manifest requests in lazy route discovery (#12915)@react-router/dev
- Handle custom envDir
in Vite config (#12969)@react-router/dev
- Fix CLI parsing to allow argument-less npx react-router
usage (#12925)@react-router/dev
- Skip action-only resource routes when using prerender:true
(#13004)@react-router/dev
- Enhance invalid export detection when using ssr:false
(#12948)
headers
/action
functions are prohibited in all routes with ssr:false
because there will be no runtime server on which to run themloader
functions are more nuanced and depend on whether a given route is prerendered
- When using
ssr:false
without a prerender
config, only the root
route can have a loader
- When using
ssr:false
with a prerender
config, only routes matched by a prerender
path can have a loader
@react-router/dev
- Error at build time in ssr:false
+ prerender
apps for the edge case scenario of: (#13021)
- A parent route has only a
loader
(does not have a clientLoader
) - The parent route is pre-rendered
- The parent route has children routes which are not prerendered
- This means that when the child paths are loaded via the SPA fallback, the parent won't have any
loaderData
because there is no server on which to run the loader
- This can be resolved by either adding a parent
clientLoader
or pre-rendering the child paths - If you add a
clientLoader
, calling the serverLoader()
on non-prerendered paths will throw a 404
@react-router/dev
- Limit prerendered resource route .data
files to only the target route (#13004)@react-router/dev
- Fix pre-rendering of binary files (#13039)@react-router/dev
- Fix typegen for repeated params (#13012)
- In React Router, path parameters are keyed by their name, so for a path pattern like
/a/:id/b/:id?/c/:id
, the last :id
will set the value for id
in useParams
and the params
prop
- For example,
/a/1/b/2/c/3
will result in the value { id: 3 }
at runtime
- Previously, generated types for params incorrectly modeled repeated params with an array
- For example,
/a/1/b/2/c/3
generated a type like { id: [1,2,3] }
.
- To be consistent with runtime behavior, the generated types now correctly model the "last one wins" semantics of path parameters.
- For example,
/a/1/b/2/c/3
now generates a type like { id: 3 }
.
@react-router/dev
- Fix path to load package.json
for react-router --version
(#13012)
Unstable Changes
react-router
- Add unstable_SerializesTo
brand type for library authors to register types serializable by React Router's streaming format (turbo-stream
) (#12264)@react-router/dev
- Add unstable support for splitting route modules in framework mode via future.unstable_splitRouteModules
(#11871)@react-router/dev
- Add future.unstable_viteEnvironmentApi
flag to enable experimental Vite Environment API support (#12936)
Changes by Package
Full Changelog: v7.1.5...v7.2.0