What is react-router-dom?
The react-router-dom package is a popular library for handling routing in React web applications. It allows developers to implement dynamic routing in a web app, which is not possible with static routing. With react-router-dom, you can define routes, navigate between them, handle parameters and query strings, and manage the history stack, among other things.
What are react-router-dom's main functionalities?
Basic Routing
This code demonstrates how to set up basic routing in a React application using react-router-dom. It uses the BrowserRouter, Route, and Switch components to define routes for different components in the app.
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
function App() {
return (
<Router>
<Switch>
<Route exact path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/contact' component={Contact} />
</Switch>
</Router>
);
}
Link Navigation
This code snippet shows how to use the Link component to create navigation links that allow users to click through different routes without causing a page reload.
import { Link } from 'react-router-dom';
function Navbar() {
return (
<nav>
<Link to='/'>Home</Link>
<Link to='/about'>About</Link>
<Link to='/contact'>Contact</Link>
</nav>
);
}
Route Parameters
This example demonstrates how to handle dynamic routes using route parameters. The useParams hook is used to access the parameters of the current route.
import { Route, useParams } from 'react-router-dom';
function User() {
let { userId } = useParams();
return <h2>User ID: {userId}</h2>;
}
function Users() {
return (
<Route path='/users/:userId' component={User} />
);
}
Programmatic Navigation
This code shows how to navigate programmatically using the useHistory hook. It allows you to push a new entry onto the history stack, mimicking the behavior of a navigation action.
import { useHistory } from 'react-router-dom';
function HomeButton() {
let history = useHistory();
function handleClick() {
history.push('/home');
}
return (
<button type='button' onClick={handleClick}>
Go home
</button>
);
}
Other packages similar to react-router-dom
reach-router
Reach Router is another routing library for React with a more straightforward, accessible approach compared to react-router-dom. It automatically manages focus for accessibility, and routing is more component-based. However, as of my knowledge cutoff in 2023, Reach Router has been officially merged with React Router, and the team recommends using React Router for new projects.
wouter
Wouter is a minimalist routing library for React and Preact that does not rely on the context API. It offers a simpler API and smaller bundle size compared to react-router-dom, making it a good choice for smaller projects or when you want to keep your project lightweight.
navi
Navi is a JavaScript library for declaratively mapping URLs to asynchronous content. It's designed to work with React and allows for lazy-loading routes, which can help improve performance in large applications. Navi provides a different approach to routing by focusing on content-first routing, which can be beneficial for certain types of applications.
This package simply re-exports everything from react-router
to smooth the upgrade path for v6 applications. Once upgraded you can change all of your imports and remove it from your dependencies:
-import { Routes } from "react-router-dom"
+import { Routes } from "react-router"
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 bad 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