This tutorial is out of date and no longer maintained.
Routing is a key aspect of web applications (and even other platforms) could not be left out in React. We can make full-fleshed single-page applications with React if we harness the powers of routing. This does not have to be a manual process, we can make use of React-Router.
In this guide, we will touch almost every aspect related to routing in React and there will be a demo so you will as well have something to play with.
You do not need to have a high experience level to follow along. The basics of React components and how to use them are enough for you to follow along in this tutorial.
You are not going to only learn how to route a React application but I will also show you the basics of tooling React using Babel, npm, and Webpack. Before we start building, let’s set that up and see what our folder structure will look like.
First, create a new project:
Follow npm init
wizard then install the following tooling dependencies:
We installed the following tooling dependencies:
Next is to configure our loader which is Webpack. Webpack is configured using a config file. So touch
the file and update the config content as follows:
The most important aspect of a Webpack config is the exported config object. The minimal code above just needs an entry point, entry
which is where bundling needs to begin. It also requires an output, output
which is where the bundled result is dumped, and then module
, which defines what loaders should be used during the bundling process. In our case, babel
is the loader we need.
We need to explicitly tell Babel which presets it should make use of. You can do this with package.json
or in a .babelrc
file. .babelrc
file is what you will see in most projects, so let’s follow that:
Define the presets:
To run Webpack we have to use a reference to the bin every time which would cause friction to our dev process. What we can do is set up scripts in the package.json
to help us with that:
The public
directory will need an entry index.html
which is very simple:
Loads the bundle and defines the DOM element to mount our React app.
Let us now define our folder structure so as to have a view of the task at hand before we start building:
# Folder Structure
|---public
|------index.html # App entry
|------style.css # Custom style
|------bundle.js # Generated
|---src # Components live here
|------car
|---------car.component.jsx
|---------car-detail.component.jsx
|------common
|---------about.component.jsx
|---------home.component.jsx
|---------main.component.jsx
|------index.jsx # Build entry
|---.babelrc # Babel config file
|---index.js
|---package.json
|---webpack.config.js # Webpack config gile
The following are wireframes of what we are up to in this tutorial:
Now that we have got a simple environment for React to live in, the next step is to set it up for routing.
React likes to keep things as simple as possible and that is why the core library just does exactly what React is about components. Routing, DOM rendering, and other logic are abstracted to a different library. To use routing, we have to pull down React, React Router, and React DOM:
A basic React component would look like this:
You can start watching and building these now with
npm run watch
. Then open another terminal and runnpm run serve
to start the server.
Adding routing features to this app is very simple. Instead of rendering the Home
component, we import Router
and Route
and use them to render the component:
The path
attribute defines the route URL and component
attribute defines the component for this route.
This kind of routing is different from what you might have seen in other UI frameworks and it is known as component routing. It is very easy to reason about because routes are also treated the same way components are treated. Routes are first-class components.
We discuss the ugly URL later in this article.
You do not need routing if the only thing you want is a single path/page as our existing example shows. Let’s add more routes to the application:
Let us do a little bit of refactoring and concern separation because that is what goes down in a real app:
We just split the codes in to separate files while being guided by our predefined folder structure. Let’s assemble in the index
file:
Nothing lost and we have a better app.
This might be a better time to invite Bootstrap to the party. Of course, our app can’t remain that ugly. Import Bootstrap in the ./public/index.html
and allow it to do its magic:
Component routes are first-class components in React, so when it comes to parenting/ownership, the same rule applies. Our app is expected to have a navigation menu that is accessible by all the main routes. We can make another parent route for all the existing routes which will have the nav-bar:
In the route setup, add another Route
component to render
that wraps the rest of the routes;
Just like every other component, the contents of the child routes are poured out where ever {this.props.children}
is found on the parent route.
Routes can be prefixed with React Router. Route prefixing is very common when building API endpoints where we have something like:
api/
is the route prefix and we can do this with React Router for nested routes:
The path
attribute will prefix all the child routes path with its value and that gives us:
There is another option to defining the root of your app (a.k.a index). IndexRoute
is another component in React-Router that handles this:
You need to import the component from React-Router:
History is a term that covers everything it takes to manage location, history, and URL in React-Router.
Up till now, we have been dealing with an ugly URL. That is not the best React-Router can offer. React-Router offers three ways to manage URLs in React apps:
At the moment our app defaults to hashHistory
and that is what is responsible for the ugly URL. browserHistory
is the recommended option for user consumption. We just need to tell React-Router to use browserHistoty
:
Import browserHistory
from React-Router:
You also need to set the base URL in the head of index.html
before it works as expected:
This works fine until you navigate to another page and reload:
This shouldn’t surprise you though because now we are making a request back to the server which does not even handle a wildcard route. Let’s use express
to fix this by creating a backend custom server with a wildcard route URL that takes us back to where we were when a reload happens:
Now we can’t use serve again so we just run with Node:
Our application is becoming more interesting and it is time to add some route links. We need to navigate with clicks and not changing URL values. Before we discuss how to add links, let’s populate our application with mock cars:
We updated our Car component to present a list of data. The data is a static array, no need for the complexity of request as this article is only about routing.
With some static data available, let’s tackle this topic. Links in React routing work well with the anchor tag but this is not recommended. Link
is a component that uses anchor internally and is the recommended way for displaying links because it plays nicer with React Router:
That is how links are used and the to
property defines the path we want to navigate to on click just like href
. Let’s update our Main
component to apply links:
We first import the Link component from React-Router then use the component for the navigation menu rather than <a>
.
For a better user experience, it is a good practice to let the user know where he/she is at by indicating with a contrasting style on the active link. Let’s define a style in our style.css
for that:
Then we use React-Router’s activeClassName
to active this style every time a respective link is activated:
We need route parameters when requesting a single item or resource for a page. Take for instance:
id
and honda-crosstour
are route parameters and we can use the value to retrieve a single car. During specification, the URLs are represented like this:
We will make use of only id
in this demo.
First thing to do is define a route that should have a route parameter:
The spotlight is on:
The path
shows that a dynamic value is expected at the id
placeholder. The CarDetail
does not exist yet so let’s make that:
Like every other component but the parameter is accessed via props
:
Don’t forget to import CarDetail
in the root index
Let’s use this ID to filter the cars array. Before we can do that we need to move the cars data array to a file that both Car
and CarDetail
component can have access to it. That should be the root then we can pass it down to the components as route props:
We now have the data array in the index.jsx
then we pass it down as a route prop:
Finally, we update the Car
component to use this data. The state is no longer needed so we can get rid of it and fetch the data from route props:
The fresh thing to learn is that we access data differently because the data was passed on to a route, not a component. Instead of:
we have:
We also used the opportunity to use Link instead of anchor tags for navigation which points:
We can filter this data now with the parameter in CarDetail
:
Redirecting is quite an easy one. We can make use of browserHistory
’s push
method to redirect. For example, we can add a button to the details page that redirects to the list page on click:
It is a common practice to restrict users from accessing a particular resource because of limitations placed on their roles in the given app. We can’t afford to allow a buyer to have access to the admin dashboard where prices can be changed. Though this logic is something that MUST be handled backend but for a better user experience, it is also important on the frontend:
We are using the onEnter
lifecycle event to listen to when this route will be hit. Once that happens, a check is run to determine if the authenticated user is an administrator or not.
This was a long read but if you followed along, you have the basics of what you need to get going with React. This article does not just serve as a tutorial but also a reference for your day-by-day routing solutions in React with React Router.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!