Optimal Routing Using React Router

React Router is a routing library for React. This library is ideal for single-page applications which have multiple views, or pages. The advantage of single-page applications is that they don’t require a page reload when new data is rendered. Thus in keeping with this feature, navigating between views need to be rendered ‘inline’ within the current page.

When writing an app with the React framework, it is important to present it in a manner which retains many of the features a typical end-user would be accustomed to when viewing multi-page applications. These include unique urls for each view, including nested views, and functioning forward and back buttons in the browser, among others.

Routing involves keeping the browser url in sync with what is on the page, and React Router apis allow for the control of data flow to be carried out in a declarative fashion. The library also lets the developer place a route component anywhere in the code where a route is to be rendered. In short, React Router conditionally renders certain components to display depending on the route being used in the URL, such as ‘/’ for the home page, '/products' for the about page, etc.

Setup

The React Router library can be installed in Node using npm. The library is comprised of three packages, two of which are environment specific: react-router, react-router-dom, and react-router-native. The native version is for mobile app development. React-router is the core package, and the dom one is used for building a website. Thus, to install, just select one of the three packages, like so:

npm install react-router-dom

Next, in an actual file, you will need to import both React and specific components from the router package, which we will go into in more detail below:

import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';

Router Components

We will look at a simple implementation in which a project will have, in addition to a ‘home’ page, two more page views. In any React application it is necessary to include code, often in a dedicated file, which renders the app to the dom. Assuming the main component to be rendered will be titled App.js, when using the React router library, we will need to wrap that rendered component in BrowserRouter tags, as follows:

ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('app')
)

Next, inside of the file to be rendered, we will need to add switch tags. These restrict the app to only render one view at a time.

function App() {
return (
<main>
<Switch>

</Switch>
</main>
)
}

It is necessary to place our route tags inside the switch tags. Route elements take a path attribute, and a component attribute which specifies which component that is to be rendered. To indicate the main or ‘home’ view, we will need to add an ‘exact’ attribute as well. This is due to the fact that without this attribute, React will route to the first component in the list that has the ‘/’ in its path. Thus the ‘exact’ attribute will only route to the exact path match described within the route tag. Here is our App() component code with the passed in route elements:

function App() {
return (
<main>
<Switch>
<Route path="/" component={Home} exact />
<Route path="/products" component={Products} />
<Route path="/locations" component={Locations} />
</Switch>
</main>
)
}

Before continuing with this example, it is worth considering how useful adding the React Router library actually is on a given project. Learning React alone already entails adhering to a specific structure for how one organizes their code: distinguishing between functional and class-based components, adding state and props and making sure data, sub-classes, and event handlers are being passed in to child components, and a host of other architectural concerns. Does it make sense to add in another layer of complexity, and does incorporating the library scale well to larger projects? To answer that, consider the code required to change between just two views: if each of the two views had different class and/or id attributes, that would have to be dealt with, likely via a ternary operator in each view’s code, in addition to another ternary operator to navigate between the two views. Both would likely require onClick() handlers as well. I will spare the reader a code example to show how this looks, but anyone who has worked with single-page apps that utilize multiple views has experienced this. React Router streamlines this process, and as a result leaves a lot of the routing tasks to the library to handle in the background.

Another component worth incorporating from this library is the error element. An error component is similar to a route tag, except it simply does not have a path. This may be added after the other route tags, in order to generate an error message if the incorrect path is specified. The message is a pre-loaded h1 tag. Here is an example:

<Route component={Error} />          

Regarding the aforementioned onClick() handlers or the necessity of anchor tags, the React Router library comes with a ‘link’ element, which generates a clickable path to a specified URL. Supposing a developer would like to incorporate a navigation bar into their application, this may be accomplished by the addition of a dedicated component which possesses link tags, as shown:

function Navigation() {
return (
<div>
<Link to="/">Home Page</Link>
<Link to="/products">Browse Products </Link>
<Link to="/locations">Our Locations</Link>
</div>
);
};

Conclusion

As I hope to have conveyed through a brief example, React Router is a powerful library that complements React for building better, declarative routes. The library can facilitate in making an application highly organized, further maintaining a separation of concerns that the React framework attempts to achieve. There are also myriad more complex tasks which the router library can accomplish, such as nested routing, generating dynamic routes which utilize path parameters, and React Router hooks. Among the countless front-end libraries to be integrated to a given project, the React Router library stands out in its ability to streamline many significant rendering operations, while not adding unnecessary complexity to a React-based application. Thank you for reading!

Sources: