Code examples | Router
Last updated
Last updated
React Router has been broken into three packages: react-router
, react-router-dom
, and react-router-native
.
You should almost never have to install react-router
directly. That package provides the core routing components and functions for React Router applications. The other two provide environment specific (browser and React Native) components, but they both also re-export all of react-router
's exports.
We are building a website (something that will be run in browsers), so we will install react-router-dom
.
When starting a new project, you need to determine which type of router to use. For browser based projects, there are <BrowserRouter>
and <HashRouter>
components. The <BrowserRouter>
should be used when you have a server that will handle dynamic requests (knows how to respond to any possible URI), while the <HashRouter>
should be used for static websites (where the server can only respond to requests for files that it knows about).
Usually it is preferable to use a <BrowserRouter>
, but if your website will be hosted on a server that only serves static files, then the <HashRouter>
is a good solution.
For our project, we will assume that the website will be backed by a dynamic server, so our router component of choice is the <BrowserRouter>
.
Each router creates a history object, which it uses to keep track of the current location 1and re-render the website whenever that changes. The other components provided by React Router rely on having that history object available through React’s context, so they must be rendered as descendants of a router component. A React Router component that does not have a router as one of its ancestors will fail to work.
If you are interested in learning more about the history
object (I think that this is important), you can check out my blog post A Little Bit of History.
Router components only expect to receive a single child element. To work within this limitation, it is useful to create an <App>
component that renders the rest of your application. Separating your application from the router is also useful for server rendering because you can re-use the <App>
on the server while switching the router to a<MemoryRouter>
.
Now that we have chosen our router, we can start to render our actual application.
Our application is defined within the <App>
component. To simplify things, we will split our application into two parts. The <Header>
component will contain links to navigate throughout the website. The <Main>
component is where the rest of the content will be rendered.
Note: You can layout your application any way that you would like, but separating routes and navigation makes it easier to show how React Router works for this tutorial.
We will define the content in the <Main>
component first. This is where we will render our routes.
The <Route>
component is the main building block of React Router. Anywhere that you want to only render content based on the location’s pathname, you should use a <Route>
element.
A <Route>
expects a path prop, which is a string that describes the pathname that the route matches — for example, <Route path='/roster'/>
should match a pathname that begins with /roster
2. When the current location’s pathname is matched by thepath
, the route will render a React element. When the path does not match, the route will not render anything 3.
Note: When it comes to matching routes, React Router only cares about the pathname of a location. That means that given the URL:
the only part that React Router attempts to match is /my-projects/one
.
React Router uses the path-to-regexp
package to determine if a route element’s path prop matches the current location. It compiles the path string into a regular expression, which will be matched against the location’s pathname. path
strings have more advanced formatting options than will be covered here. You can read about them in the path-to-regexp
documentation.
When the route’s path matches, a match object with the following properties will be created:
| the matched part of the current location’s pathname |
| the route's path |
|
|
| an object containing values from the pathname that were captured by |
You can use this route tester to play around with matching routes to URLs.
Note: Currently, a route’s path must be absolute 4.
<Route>
s can be created anywhere inside of the router, but often it makes sense to render them in the same place. You can use the <Switch>
component to group<Route>
s. The <Switch>
will iterate over its children elements (the routes) and only render the first one that matches the current pathname.
For this website, the paths that we want to match are:
| the homepage |
| the team’s roster |
| a profile for a player, using the player’s number |
| the team’s schedule of games |
In order to match a path in our application, all that we have to do is create a <Route>
element with the path prop we want to match.
Routes have three props that can be used to define what should be rendered when the route’s path matches. Only one should be provided to a <Route>
element.
component
— A React component. When a route with a component prop matches, the route will return a new element whose type is the provided React component (created using React.createElement
).
render
— A function that returns a React element 5. It will be called when the path matches. This is similar to component
, but is useful for inline rendering and passing extra props to the element.
children
— A function that returns a React element. Unlike the prior two props, this will always be rendered, regardless of whether the route’s path matches the current location.
Typically, either the component
or render
prop should be used. The children prop can be useful occasionally, but typically it is preferable to render nothing when the path does not match. We do not have any extra props to pass to the components, so each of our <Route>
s will use the component
prop.
The element rendered by the <Route>
will be passed a number of props. These will be the match
object, the current location
object 6, and the history
object (the one created by our router) 7.
Now that we have figured our root route structure, we just need to actually render our routes. For this application, we will render our <Switch>
and <Route>
s inside of our <Main>
component, which will place the HTML generated by a matched route inside of a <main>
DOM node.
Note: The route for the homepage includes an exact
prop. This is used to state that that route should only match when the pathname matches the route’s path exactly.
The player profile route /roster/:number
is not included in the above <Switch>
. Instead, it will be rendered by the <Roster>
component, which is rendered whenever the pathname begins with /roster
.
Within the <Roster>
component we will render routes for two paths:
/roster
— This should only be matched when the pathname is exactly /roster
, so we should also give that route element the exact
prop.
/roster/:number
— This route uses a path param to capture the part of the pathname that comes after /roster
.
It can be useful to group routes that share a common prefix in the same component. This allows for simpler parent routes and gives us a place to render content that is common across all routes with the same prefix.
As an example, <Roster>
could render a title that would be displayed for all routes whose path begins with /roster
.
Sometimes there are variables within a pathname that we want to capture. For example, with our player profile route, we want to capture the player’s number. We can do this by adding path params to our route’s path
string.
The :number
part of the path /roster/:number
means that the part of the pathname that comes after /roster/
will be captured and stored as match.params.number
. For example, the pathname /roster/6
will generate a params object:
The <Player>
component can use the props.match.params
object to determine which player’s data should be rendered.
You can learn more about path params in the path-to-regexp
documentation.
Alongside the <Player>
component, our website also includes <FullRoster>
, <Schedule>
, and <Home>
components.
Finally, our application needs a way to navigate between pages. If we were to create links using anchor elements, clicking on them would cause the whole page to reload. React Router provides a <Link>
component to prevent that from happening. When clicking a <Link>
, the URL will be updated and the rendered content will change without reloading the page.
<Link>
s use the to prop to describe the location that they should navigate to. This can either be a string or a location object (containing a combination of pathname
, search
, hash
, and state
properties). When it is a string, it will be converted to a location object.
Note: Currently, a link's pathname must be absolute 4.