Web sites require a way to display different pages when a different URL is requested. Frameworks like Angular or Vue have integrated features for handling the routing of the web app. However, React is just a UI library and it does not have implemented a routing mechanism. It relies on third party libraries to handle this behavior.
In this article we will learn the basics of React Router v.4, a third party powerful library build for handling routing in React apps.
What to expect from this article?
We will go through the basics of the library, explaining how all the features fit together and how they are implemented in React. After reading this article you will learn how to:
- Set a
BrowserRouter
component to keep the UI in sync with the URL - Set different
Route
components to handle rendering of the App components - Navigate between routes with
Link
andNavLink
components - Redirect to different
Route
components - Display 404 Custom components with
Switch
- Use
match
object to access path, parameters and url information - Navigate to a Route programmatically with the
history
object
Getting Started
First make sure you install react-router-dom
which is the package that contains the React components.
> yarn add react-router-dom
Now you are set!
Main Router Components
React Router has two main components, BrowserRouter
and Route
. The first one, is the root routing component and it helps to keep the UI in sync with the URL. Route
renders an App's component when the URL matches the Route
component. See an example below:
import React from 'react';
import {
BrowserRouter,
Route
} from 'react-router-dom';
// App Components
import Home from './Home';
import About from './About';
import Contact from './Contact';
const App = () => (
<BrowserRouter>
<div className="container">
<Route path="/" component={ Home } />
<Route path="/about" component={ About } />
<Route path="/contact" component={ Contact } />
</div>
</BrowserRouter>
);
By wrapping the root component with BrowserRouter
we will have more control on what is rendered into the screen.
The Route
components have two properties in the last example, path
and component
. With path
we specify the path we want to match with our component. We pass the component to the component
property so it can be rendered.
There is a small bug in the last example, when we navigate to "/about"
or "/contact"
in the url, the component Home
will be rendered. this is because "/"
is also matching with both paths. We should specify the Route
that we want to match the exact path. See code snippet below:
...
<Route exact path="/" component={ Home } />
...
With the exact
property, we tell the Route component to match the exact path.
Another way to render a component with Route
, is by specifying a render property that takes a callback. This callback should return a component to render.
...
<Route path="/about" render={ () => <About title="About" /> } />
...
Instead of using the component
property, we specify a render
property that renders a component. The difference is that we can pass properties to that component like a title.
Navigating Between Routes
There a two ways to implement links with React Router. We can use a Link
component that will render a simple <a href=""></a>
tag.
import { Link } from 'react-router-dom';
const Navbar = () => (
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
);
With Link
we just need to specify a to
property which is the same as href
.
The problem with Link
is that we can't know if a navbar link is active or not. For this we have NavLink
which gives and active class when when we navigate to that link.
import { NavLink } from 'react-router-dom';
...
<NavLink to="/">Home</NavLink>
// this renders: <a href="/" class="active">Home</a>
...
If you want a custom active class, set the activeClassName
property or set the active styles with the activeStyle
property.
...
<NavLink to="/" activeClassName="nav-link--active">Home</NavLink>
// this renders: <a href="/" class="nav-link--active">Home</a>
<NavLink to="/about" activeStyle={{ color: "tomato" }}>About</NavLink>
// this renders: <a href="/about" style="color:'tomato'">About</a>
...
Now you can use some CSS to customize the look of your active nav links.
Redirecting to Other Components
The Redirect
component redirects the url to another Route
. Just specify the to
property. Most of the time, this component is rendered by another Route
component, to redirect the user when a certain url matches the Route
path.
import { Redirect } from 'react-router-dom';
...
<Route
exact
path="/articles"
render={ () => <Redirect to="/articles/all" } />
...
When a user visits "/articles"
, he/she will be redirected to "/articles/all"
.
Using 404 Custom Components
When a user visits a route that is not specified by the app, nothing will be rendered. This is why we need to implement a way to handle 404 Not found pages. With Switch
we can wrap all the Route
components to render only the first to match, and at the end declare a default Route
component that does not have a path
property.
import { Switch } from 'react-router-dom';
...
<Switch>
<Route exact path="/" component={ Home } />
<Route path="/about" component={ About } />
<Route path="/contact" component={ Contact } />
<Route component={ NotFound } />
</Switch>
...
If the url does not match any of the Route
components, the NotFound
component will be rendered.
The match
Object
BrowserRouter
sends it's Route
children an object with information about the url, the path and the parameters that where passed through the url. This object is called match
and it can be accessed by any component rendered by a Route
.
import React from 'react';
import { NavLink } from 'react-router-dom';
const Header = ({ match }) => (
<NavLink to={`${match.path}/some-article`}>Some Article</NavLink>
);
Another example would be to send URL parameters from a Route
component, and access the parameters in the rendered component.
import React from 'react';
import { Route } from 'react-router-dom';
const Header = () => (
<Route path={`articles/:title`} component={ Article } />
);
const Article = ({ match }) => (
<h1>{ match.params.name }</h1>
);
Notice that to specify a URL parameter we need to add :my-param
before the parameter name, which can be anything.
Navigating Between Routes Programmatically
Similar to the match
object, Route
components have access to the history
property, which contains information about all the URLs visited. Additionally, a new URL can be set by pushing it into the history
array.
handleClick = e => {
let newUrl = 'articles/react-router-basics';
props.history.push(newUrl);
}
By adding newUrl
to the history
array, the user will be redirected the newly inserted URL.
Conclusion
In this article we went over the basics of React Router v.4, a routing library build for React apps. We covered the following:
BrowserRouter
andRoute
are the main components exposed by thereact-router-dom
library- With
BrowserRouter
we can maintain the URL and the UI in sync - With
Route
we manage which parts of the UI should render when a certain path is requested - We can navigate through the App routes with
Link
andNavLink
BrowserRouter
child components have access to information about the url, path and parameters with thematch
object.- A
Route
can be programmatically assigned by pushing a new url to thehistory
array.
You made it until the end!
These articles are meant to be an exercise in my learning journey but if they help you as well, that is a happy coincidence!
If you have some comment or suggestion please contact me, I’ll be happy to see some feedback or suggestion topics for my next articles.
Thanks a lot for your time! You are the best!