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 a location
matches the route's path
.
Consider the following code:
import { BrowserRouter as Router, Route } from 'react-router-dom'
<Router>
<div>
<Route exact path="/" component={Home}/>
<Route path="/news" component={NewsFeed}/>
</div>
</Router>
If the location of the app is /
then the UI hierarchy will be something like:
<div>
<Home/>
<!-- react-empty: 2 -->
</div>
And if the location of the app is /news
then the UI hierarchy will be:
<div>
<!-- react-empty: 1 -->
<NewsFeed/>
</div>
The "react-empty" comments are just implementation details of React's null
rendering. But for our purposes, it is instructive. A Route is always technically "rendered" even though its rendering null
. As soon as the app location matches the route's path, your component will be rendered.
There are 3 ways to render something with a <Route>
:
Each is useful in different circumstances. You should use only one of these props on a given <Route>
. See their explanations below to understand why you have 3 options. Most of the time you'll use component
.
All three render methods will be passed the same three route props
A React component to render only when the location matches. It will be rendered with route props.
<Route path="/user/:username" component={User}/>
const User = ({ match }) => {
return <h1>Hello {match.params.username}!</h1>
}
When you use component
(instead of render
or children
, below) the router uses React.createElement
to create a new React element from the given component. That means if you provide an inline function to the component
prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. When using an inline function for inline rendering, use the render
or the children
prop (below).
This allows for convenient inline rendering and wrapping without the undesired remounting explained above.
Instead of having a new React element created for you using the component
prop, you can pass in a function to be called when the location matches. The render
prop receives all the same route props as the component
render prop.
// convenient inline rendering
<Route path="/home" render={() => <div>Home</div>}/>
// wrapping/composing
const FadingRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
<FadeIn>
<Component {...props}/>
</FadeIn>
)}/>
)
<FadingRoute path="/cool" component={Something}/>
Warning: <Route component>
takes precedence over <Route render>
so don't use both in the same <Route>
.
Sometimes you need to render whether the path matches the location or not. In these cases, you can use the function children
prop. It works exactly like render
except that it gets called whether there is a match or not.
The children
render prop receives all the same route props as the component
and render
methods, except when a route fails to match the URL, then match
is null
. This allows you to dynamically adjust your UI based on whether or not the route matches. Here we're adding an active
class if the route matches
<ul>
<ListItemLink to="/somewhere"/>
<ListItemLink to="/somewhere-else"/>
</ul>
const ListItemLink = ({ to, ...rest }) => (
<Route path={to} children={({ match }) => (
<li className={match ? 'active' : ''}>
<Link to={to} {...rest}/>
</li>
)}/>
)
This could also be useful for animations:
<Route children={({ match, ...rest }) => (
{/* Animate will always render, so you can use lifecycles
to animate its child in and out */}
<Animate>
{match && <Something {...rest}/>}
</Animate>
)}/>
Warning: Both <Route component>
and <Route render>
take precedence over <Route children>
so don't use more than one in the same <Route>
.
Any valid URL path that path-to-regexp@^1.7.0
understands.
<Route path="/users/:id" component={User}/>
Routes without a path
always match.
When true
, will only match if the path matches the location.pathname
exactly.
<Route exact path="/one" component={About}/>
path | location.pathname | exact | matches? |
---|---|---|---|
/one |
/one/two |
true |
no |
/one |
/one/two |
false |
yes |
When true
, a path
that has a trailing slash will only match a location.pathname
with a trailing slash. This has no effect when there are additional URL segments in the location.pathname
.
<Route strict path="/one/" component={About}/>
path | location.pathname | matches? |
---|---|---|
/one/ |
/one |
no |
/one/ |
/one/ |
yes |
/one/ |
/one/two |
yes |
Warning: strict
can be used to enforce that a location.pathname
has no trailing slash, but in order to do this both strict
and exact
must be true
.
<Route exact strict path="/one" component={About}/>
path | location.pathname | matches? |
---|---|---|
/one |
/one |
yes |
/one |
/one/ |
no |
/one |
/one/two |
no |
A <Route>
element tries to match its path
to the current history location (usually the current browser URL).
However, a location
with a different pathname
can also be passed for matching.
This is useful in cases when you need to match a <Route>
to a location other than the current history location, as shown in the Animated Transitions example.
If a <Route>
element is wrapped in a <Switch>
and matches the location passed to the <Switch>
(or the current history location), then the location
prop passed to <Route>
will be overridden by the one used by the <Switch>
(given here).
When true
, will match if the path is case sensitive.
<Route sensitive path="/one" component={About}/>
path | location.pathname | sensitive | matches? |
---|---|---|---|
/one |
/one |
true |
yes |
/One |
/one |
true |
no |
/One |
/one |
false |
yes |