A bluffer’s guide to React Router v4

The important things you can quickly learn to be informed and confident with using and conversing on React Router v4

Obligatory image of complex train routing only abstractedly related to this article. Image courtesy of https://en.wikipedia.org/wiki/Rail_transport#/media/File:CTA_loop_junction.jpg

React Router is a client-side router (CSR) for use with React projects (I know, duh right?). It provides routing which is the fancy term for the rendering of different components depending on URL paths within a React web application.

Run the following command in your project to save react-router-dom as a project dependency:

Using the ES2015 syntax, you can import React Router into your React components using:

Link components can be thought of as your typical anchor links that, when clicked, redirect the user to the path specified in its to property.

Route components can be thought of as the controller for the render. When you see these components, just think this is what they say:

WHEN I see the URL as what is specified in my path property, THEN I will render the component listed in my component or render property.

The basic example below is mostly lifted from ReactTraining’s basic example:

Nesting routes is exactly the same as creating high-level routes, except for defining a BrowserRouter component (as your nested routes are composed within the high-level BrowserRouter component anyway). It simply needs more Link and Route components. We can indefinitely nest further routes within any other nested routes.

In the previous example, we had different components defined for each topic in nested routes. In the following example, we have a single Topic component that is rendered for the three different routes. The Topic component dynamically renders the topicId, which is passed as a property by the Route, and its value defined as part of the URL using the :.

When a Route defines a component to render, it passes a match object to its props (along with location and history, but unimportant for now). This match object has a params object which contains any variables passed by Route defined using the : notation in the path URL (aka Route Parameter).

In this way, we can cut down on separately creating components for each Link and instead make one re-usable component rendered with the information passed to it.

When creating nested links, our Link component still needs to refer to the entire URL path instead of the location it’s really concerned with. This means that nested links would have hard-coded locations to its parent links, which isn’t great when a name change occurs and a big renaming effort is required.

Instead, using the match object passed by Route, we can dynamically refer to it’s location and use that to avoid hard-coding.

For example:
<Route path="/topics" component={Topics}/> passes a match object with a url property with the value "/topics" . Topics , via its props, can reuse the match.url when defining its nested links.

By default, when you specify Route components, each matching path will be rendered inclusively. Using URL parameters, this becomes problematic. As the parameter effectively acts as a wildcard (so any text is found as matching), you will find that when these are mixed with hard-coded routes, they both will display. Using exact won’t help either.

React Router’s solution is the Switch component. The Switch component will render the child Route component on the first matching path exclusively. This means that if all hard-coded routes are specified first, then these will be rendered only.

There are times when you don’t want ambiguous matching of Route components, but there will be times when you do.

Remembering that we can think of Route as a simple “WHEN I see this path, THEN render this component”, which means we can have multiple Route components matching a single page, but providing different content.

In the below example, we use one component to pass the URL parameter to show the user their current path, and another component that renders with the content component. That means two different components are rendered for the one URL path.

A Route component can be passed a component to render if one is available. It can also render a component directly using the render property.

URL passed parameters are fine, but what about passing in properties that require more data to components, such as objects? Route doesn’t allow you to append properties it doesn’t recognize.

However what can be done to pass properties is to use Route render method.

You can also pass properties to a component via the Link component. Instead of passing in a String to the to property, we can pass in an object instead. On this object, we can declare the pathname representing to URL we want to navigate to. We also declare a state object that contains any custom properties we want. These properties are contained on the location object (in location.state).

In the below example (contrived, I know…), we pass in a message property to display on a page.

You can use the Redirect component to redirect the users’ immediate URL to another.

In the below example, we see a redirect for a user depending on whether the isAuthenticated state on component RedirectExample is true or false, appropriately redirecting if they’re logged in (to /home) or logged out (to /dashboard):

Another way to redirect is by using the higher-order component withRouter. This allows you to pass the properties of Route (match, location, and importantly in this example history) to components that aren’t rendered via the typical Route component. We do this by wrapping our exported component with the withRouter.

Why is having history important? We can use history to force redirection by pushing a URL to the history object.

There are caveats to this way of routing which I don’t detail (see the withRouter documentation). Also, the exported component must still be composed within another component that is rendering withinBrowserRouter (which I don’t show in this example).

There will be times when a Link may refer to a URL that has no corresponding <Route path='/something' component={Something}/> . Or a user will type an incorrect URL in the browser bar.

When that happens, all we will have is a non-responsive page or link where nothing happens (which is not as bad as actually being navigated to a non-existent page).

Most times we want to at least show the user we can’t find their content, maybe with a witty image like Github’s 404 page. In this case, you’ll want a default component, also known as a no-match or catch-all component.

When a user clicks a link (or indeed types something incorrectly in the browser navigation bar), so long as there are no other matching components, we will be directed to the default component to be rendered.

Note the use of Switch (ambiguous matching with URL parameters). As this Route has no path, it will be effectively always rendered. We require a Switch to only render if it cannot find any other matching Route path’s.

The Link component at its core renders an anchor element for whatever is passed as its to property. There are times when we would want customizations made to the Link component without having to have these customizations everywhere. React Router allows a means of doing this is by creating a custom link (see React Router training guide for more info — we use their example more or less below).

For a custom link, one is essentially wrapping the existing Link component inside a custom component, and providing additional information, not unlike the Higher Order Component pattern.

In our example, we only show the links for the pages that aren’t displayed. For our CustomLink component to have the knowledge of what page is currently displayed, we need to wrap the Link component in a Route component so that we can pass the match object that comes with React Router’s Route. We pass this wrapping our Link component as a child to the Route component.

Route, if you remember, simply checks the current path and when we match, will render “something” (either defined by the component/render properties or as as a child of Route — such as our Link component).

We subvert this slightly with an equality check to say if we don’t find a match object (if our current path doesn’t match what’s defined in the path property in the Route declared in CustomLink), then render a Link, otherwise render nothing.

Query strings are parameters in the URL that look like variables and are prefixed by the question mark (such as www.example.com/search?name=Greg ).

I’m going to rip the band-aid off quick — React Router doesn’t come with a way to parse query strings 😮. It does, however, locate query strings as a String in its passed properties, within location.search, wherein the above example would be defined as search: "?name=Greg".

So what to do? There are a number of ways to solve this problem, including reinventing the wheel. I would like to anecdotally highlight the npm package query string as a solution which I’ve used and has become my de facto query string parser.

React Router v4 comes with a Prompt component, which as you can guess, displays a prompt to the user. This is useful as UX feature for users when they are warned of potentially losing form data if they transition from the current form page.

The basic pattern in implementing a navigational prompt is to have a boolean state property which decides whether they should be prompted or not. This state is updated via the form based on whether there are values selected for any form field. Within the form, you render a Prompt component, passing in two properties: a when (which is your boolean state set earlier) and a message to display.

Below is an example (it mostly follows the example from ReactTraining prevent transitions):


In the article, you will have learned all the basics to use React Router in your web applications. You should be even able to converse with your many friends and family about the joys of React Routing.

If you liked this article, please share your like with a friendly clap.

If you didn’t like this article and would like to register your resentment, you can do so by giving a hateful clap.

The opinions expressed in this publication are those of the author. They do not purport to reflect the opinions or views of any organization or business that the author may be connected to.



We’ve moved to https://freecodecamp.org/news and publish tons of tutorials each week. See you there.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Greg Byrne

Engineer of Software. Breaking life’s hurdles with peregrine speed and a manatee’s grace.