Web Development

A Programmer’s Guide to React Router

July 2nd, 2019 | By Camilo Reyes | 5 min read

React Router is a lightweight library that does dynamic routing. It works like any React component because URL routes can mutate when rendering components. In this take, we’ll explore React Router using stock data. We’ll put the data in a static JSON file, but this data can come from dynamic sources.

This is a complete programmer's guide to adding a React Router to a React application. You can find the complete source code for this tutorial in this GitHub repo.

Feel free to follow along. We will assume no knowledge of React Router and little experience with React. To begin, fire up a new create-react-app:

npx create-react-app programmers-guide-react-router --typescript


We’ll include TypeScript with a --typescript parameter to add type safety. This helps to conceptualize the stock data that goes through each route.

Go ahead and keep the existing App.tsx, as we’ll be reusing some of it.

The initial Create React App template has enough to begin, minus one dependency. To install React Router, do:

npm i react-router-dom --save


Because it needs type definitions, do:

npm i @types/react-router-dom --save-dev


Inside App.tsx, import all components necessary:

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


We’ll cover what each one does as we flesh out stock data with data-driven routes. Be sure to get the App component down to the bare bones:

class App extends Component<{}, AppState> {
 render() {
   return (
     <div className="App">
       <header className="App-header">

         // TODO: dynamic routes go here

         <p style={{position: "absolute", bottom: 0}}>
           Programmer’s Guide to React Router
         </p>
       </header>
     </div>
   );
 
}


Navigation

The data will be a list of stock information, for example, stock symbol, name, and description. To help visualize this in TypeScript, add a state-type declaration:

interface AppState {
 stocks: Array<StockState>
}

interface StockState {
 name: string;
 symbol: string;
 description: string;
 value: number;
}


These types can define the state of the App component:

state: AppState = {
 stocks: []
};


The navigation data that generates the link collection comes from a JSON file on the server. We’ll use fetch to put this stock data in place and mutate the state:

async componentDidMount() {
 const payload = await fetch('/stocks.json');
 const data: Array<StockState> = await payload.json();

 this.setState({stocks: data});
}


We’re using async/await by placing an async prefix in componentDidMount. This makes the code block look like synchronous code to improve readability. The await keyword expects a Promise<any> and only executes the next line when fulfilled.

Inside the render() method, a map function is useful for getting a list. The NavLink component creates the link collection.

const links = this.state.stocks.map(s =>
 <NavLink to={"/" + s.symbol}
   key={s.symbol}
   className="App-link" style={{marginRight: "1em"}}
   activeStyle={{color: "white", textDecorationLine: "none"}}>
   {s.symbol}
 </NavLink>);


Note the key prop: React needs this anytime it has a list of components. The to prop has the route where the link will go. Be sure to prefix this with "/" so it matches the current route and activates. The activeStyle prop sets the CSS style when the route is active.

Place the link collection inside the return() statement, right below the header tag:

<BrowserRouter>
 <p>
   {links}
 </p>
</BrowserRouter>


The NavLink component must be wrapped around a BrowserRouter component. This enables dynamic routes in the React Router.

Dynamic Routers

The Route component renders any React component when the route is active. Using stock data, we can create a list of components per route:

const routes = this.state.stocks.map(s =>
 <Route key={s.symbol} path={"/" + s.symbol}
   render={() => <StockComponent {...s} />} />);


Note the prefix "/" — this is so it has an exact match to the route. With the render prop, it is possible to set any number of props in the rendering component.

The StockComponent will use props that come from stock data when it renders. React Router uses rendering props to give you this flexibility. The render prop takes a callback function with a single parameter. For example, if (props) => <></>, placing a props argument in the callback gives you access to the parent’s props.

These routes can go below the link collection in the BrowserRouter component, for example:

<Switch>
 {routes}
</Switch>


A Switch component works much like a switch statement in JavaScript. It picks the first match, renders the route component, and exits. If you have a Route that’s set to match a homepage like "/", be careful. It’ll need an exact prop in the Route component. Or set it as the fallback route by placing it last in the switch component.

Stock Component

For the StockComponent, props come from StockState. We can inherit StockProps from the state to make this distinction clear in the code. For example:

interface StockProps extends StockState {
}


This is a nice, clean way of reusing type declarations while making the code explicitly clear. The stock component can then use StockProps as the type:

const StockComponent: React.FC<StockProps> =
 ({name, symbol, value, description}) =>
 <>
   <p style={{textAlign: "left"}}>
     {name} <br />
     Symbol: {symbol} <br />
     Value: ${value}
   </p>

   <p style={{textAlign: "justify", margin: "1em 2em"}}>
     {description}
   </p>
 </>;


This is a functional component, often called a stateless component, because it does not mutate state. TypeScript makes it easy to conceptualize this component while adding type safety.

Clicking on each link now renders the stock component with route prop data. Because it is dynamic, changing the JSON file also changes the link collection and each route.

This is what all the components look like:
React-Router-example

Conclusion

React Router is a nice, simple way to put dynamic routing in place. The BrowserRoute component encapsulates both navigation links and route components.

The NavLink component has props like activeStyle to change style when the route activates. Dynamic routers can go into a Switch component that acts like a switch statement. For each route, a React component can render with rendering props.

The library has a lot of flexibility, so you can render all React components on a single page. It has features that work well in the browser, such as navigating between routes with the back button. All this, while embracing React components in a lightweight package.

Don't forget that if you're building React applications with sensitive logic, you should always protect them against abuse, tampering, and reverse-engineering.

Jscrambler

The leader in client-side Web security. With Jscrambler, JavaScript applications become self-defensive and capable of detecting and blocking client-side attacks like Magecart.

View All Articles

Must read next

Javascript

Getting Started with Firestore and React Native

By following this guide, you'll be able to build your own React Native project using a Firestore database.

June 11, 2019 | By Aman Mittal | 7 min read

Web Development

Introduction to Vue Router

Vue router is one of the most popular libraries for Vue.js. In this blog post, we explore its many features and how you can leverage them.

February 11, 2020 | By John Au-Yeung | 11 min read

Section Divider