Javascript

Understanding how to code ReactJS | React Routing

Understanding how to code ReactJS | React Routing
Dhaval Patel

Dhaval Patel

Nov 02, 2018

In this course section, we will be breaking the concept of react routing, how it works and various methods of doing it. Is that a tough job? Believe me, it’s as simple as writing any other simple line of code. Just a basic understanding and you will be a pro in applying it every time you use.

Before you proceed with this article, I would suggest to watch out part 1 which is Basic Setup and General Understanding of this series where I have created a project setup and created some components which we will be using throughout this series.

What is React Router?

React router is a special library that enable users to switch between different pages of the website without reloading the browser every time. It is useful in creating what is called as Single Page Application or a SPA.

For implementing routing in our application, we will need to install it to the project. Let’s install it using npm.

npm install --save react-router-dom

Once it is installed, we will make some changes to our existing files and create a new file at the root level for routing to keep all our routing code in a separate place. You can find the complete source code of this project on a free public github and play around with it.

MyShoppingAppRoutes.js

import React, {Component} from 'react';
import {BrowserRouter, Route} from 'react-router-dom';
import Products from './containers/Products/Products';
import About from './components/About/About';
import Product from './components/Product/Product';

class MyShoppingAppRoutes extends Component {
  render() {
    return (<div>
      <BrowserRouter>
        <div>
          <Route exact path="/" component={Products} />
          <Route exact path="/about" component={About} />
          <Route exact path="/product" component={Product} />
        </div>
      </BrowserRouter>
    </div>)
  }
}

export default MyShoppingAppRoutes

We have created a new file to manage all our routes at one place MyShoppingAppRoutes.js. It imports 2 components from the react-router-dom library which are BrowserRouter and Route. BrowserRouter is a wrapper component which wraps all our routes within itself. Route component is used to define every explicit route available in our project. It helps find page to any specified route of the application. In routes, we have defined the exact property which actually checks for exact match of the selected route.

I have made some changes in some of our existing pages for creating the setup for react router more precisely like in MyShoppingApp.js, I have replaced Layout component with MyShoppingAppRoutes so at the time of initial rendering, we have all our pages protected by a route for them.

MyShoppingApp.js

import React, { Component } from 'react';
import './MyShoppingApp.css';
import MyShoppingAppRoutes from './MyShoppingAppRoutes';

class MyShoppingApp extends Component {
  render() {
    return (
      <div className="App">
        <MyShoppingAppRoutes />
      </div>
    );
  }
}

export default MyShoppingApp;

In Layout.js file, I have replaced Product component by the children of our wrapper Layout component. Whenever we wrap any component in a hoc, we can extract the complete jsx of the child component through this.props.children property in the higher order component.

Layout.js

import React, {Component} from 'react';
import Header from '../../components/Navigation/Header/Header';

class Layout extends Component {
  render() {
    let element;
    if (this.props.children) {
      element = this.props.children
    }
    return (<div className="wrapper">
        <Header />
        {element}
      </div>)
  }
}

export default Layout;

We have created 2 more routes in our routing file which is for the About and Product modules. Product is another component that is used to render information of any specific product from the list. We don’t have these components created so far, but don’t worry, we are about to bring them on board.

About.js

import React, {Component} from 'react';
import Layout from '../../hoc/Layout/Layout';

const about = (props) => (<Layout>
  <div className="container">
    <div className="card my-5">
      <div className="card-body">
        <h5 className="card-title">Polo t-shirt</h5>
        <p className="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</p>
        <p className="card-text">It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.</p>
      </div>
    </div>
  </div>
</Layout>)

export default about;

Product.js

import React, {Component} from 'react';
import Layout from '../../hoc/Layout/Layout';

const product = (props) => (<Layout>
  <div className="container">
    <div className="card my-5">
      <div className="card-body">
        <div className="row ">
          <div className="col-4">
            <img className="img-fluid" src="https://via.placeholder.com/350x300" alt="Card image cap"/>
          </div>
          <div className="col-8">
            <h5 className="card-title">Polo t-shirt</h5>
            <h6 className="card-title">Price : $20</h6>
            <p className="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</Layout>)
export default product;

These are the 2 new components, About.js and Product.js. As you see these are not class based components unlike our Projects component as these are the dumb components which does not do anything on their own but just display the information to the view. Since we are not doing any state update in here or calling any lifecycle hook, I have made them stateless components which helps improve performance of any application.

Since these components are also not acting as a container to any other component, I have kept them in the components folder instead of the containers folder. This is my personal preference, you can keep it either way you need.

So now when we have the routing setup and pages ready, let’s bring them in action by navigating to different pages and give them more of a SPA feel. To get more into the routing concept, we will do routing in 2 manners:

  1. By Link
  2. Programatically

Let’s start with Header.js, remember, we have 2 links for Home and About over there.

Header.js

import React, {Component} from 'react';
import { Link, withRouter } from 'react-router-dom';

class Header extends Component {
  render() {
    return (<header>
        <div className="container">
          <nav className="navbar navbar-expand-lg navbar-light bg-light">
            <a className="navbar-brand" href="#">My Shopping App</a>
            <button className="navbar-toggler" type="button">
              <span className="navbar-toggler-icon"></span>
            </button>
            <div className="collapse navbar-collapse" id="navbarSupportedContent">
              <ul className="navbar-nav ml-auto">
                <li className="nav-item">
                  <Link className={(this.props.match.path == '/') ? "nav-link text-primary" : "nav-link"} to="/">Home</Link>
                </li>
                <li className="nav-item">
                  <Link className={(this.props.match.path == '/about') ? "nav-link text-primary" : "nav-link"} to="/about">About</Link>
                </li>
              </ul>
            </div>
          </nav>
        </div>
      </header>)
  }
}

export default withRouter(Header);

The above code seems quite confusing right? Link, withRouter, what are these? Alright, let’s understand what are these and why I used that.

Link: Link, provided by react-router-dom is generally a sort of <a> tag you use in html, but it has various advantages over <a> tag in html. Link allow us to navigate through the pages without reloading the view. It require a path where we need to navigate to and we can pass more of parameters into it based on our requirement. You can view the documentation for more details on Link tag.

withRouter: The withRouter component that we used is generally to have access to the props of the currently visible route. Whenever we are having a parent child relationship between components. By default, props of any component are not passed to any other component in relation with it. withRouter lets us have access to pass props between related components whenever we define it. We used it to have access to the props of currently viewed page so as to change the className dynamically from the header based on the active page.

Now lets navigate from the Products route to the Product route whenever any item on the page is clicked.

MyShoppingAppRoutes.js

import React, {Component} from 'react';
import {BrowserRouter, Route} from 'react-router-dom';
import Products from './containers/Products/Products';
import About from './components/About/About';
import Product from './components/Product/Product';

class MyShoppingAppRoutes extends Component {
  render() {
    return (<div>
      <BrowserRouter>
        <div>
          <Route exact path="/" component={Products} />
          <Route exact path="/about" component={About} />
          <Route exact path="/product/:id" component={Product} />
        </div>
      </BrowserRouter>
    </div>)
  }
}

export default MyShoppingAppRoutes

Products.js

import React, {Component} from 'react';
import Aux from '../../hoc/Aux/Aux';
import Layout from '../../hoc/Layout/Layout';

class Products extends Component {
  goToProductListingHandler = () => {
    this.props.history.push({pathname: "product/1"});
  }
  render() {
    return (<Aux>
      <Layout>
      <div className="container my-5">
        <div className="row products-list">
          <div className="col-4">
            <div className="card">
              <img className="card-img-top" src="https://via.placeholder.com/350x200" alt="Card image cap"/>
              <div className="card-body">
                <h5 className="card-title" onClick={this.goToProductListingHandler}>Polo t-shirt 1</h5>
                <p className="card-text">Price : $20</p>
                <a href="#" className="btn btn-primary">Add</a>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div className="container">
        <table className="table table-bordered text-center">
          <thead>
            <tr>
              <th scope="col">#</th>
              <th scope="col">Name</th>
              <th scope="col">Price</th>
              <th scope="col">quantity</th>
              <th className="text-primary" scope="col">Total</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th scope="row">1</th>
              <td>Polo t-shirt 1</td>
              <td>$20</td>
              <td>1</td>
              <td>$20</td>
            </tr>
            <tr>
              <th></th>
              <td></td>
              <td></td>
              <td></td>
              <td className="font-weight-bold text-primary">$20</td>
            </tr>
          </tbody>
        </table>
      </div></Layout>
    </Aux>)
  }
}

export default Products;

To navigate through the pages programmatically, I have made changes in MyShoppingAppRoutes.js file to expect a id of the product it’s been navigated to. Now in Products.js, instead of using Link, I have created a handler to call a function. In props inside history object, we have push method that lets the page navigate to the specified path. I have passed 1 as a static value to it for now. We will soon replace it when working with http and axios.

So I think it’s time to conclude this part of our learning. In here, we have learned a lot about routing through links and programmatically, how to setup and more. Super easy, right? Follow along the series and do comment your thoughts or any question that you may have. In the part 3 of this series, we will fetch data from a json file using http and axios and bring our project into life.

Hire Experts, Build Excellence!

Let us Connect With You To Turn Ideas Into Reality!