React Router

I. React Router

By default, React comes without routing.

React Router allows us to build a single-page web application with navigation without the page refreshing when the user navigates.

II. Setting up the project

Firstly, we need to create a new React app by running the following command:

npx create-react-app my-app

III. Installing React Router

To install React Router, we use the following command:

npm install react-router-dom

After the installation, we can check the version of react-router-dom in package.json file.

"dependencies": {
    "react-router-dom: "^5.2.0"
}

Documentation: https://reactrouter.com/web/guides/quick-start

IV. Setting up the Router

To use React Router in our app, we need to import the package BrowserRouter from react-router-dom:

import React from "react";

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

const App = () => {
  return (

  );
};

export default App;

To enable routing in our entire app, we need to wrap all our return into the <Router>

const App = () => {
  return (
    <Router>

    </Router>
  );
};

V. Setting up the routes

For example, we need to set up routings for 3 pages

  • Home page
  • About page
  • Contact page

Step 1: Import 3 components that will become our pages:

// Import pages
import Home from "./Home";
import About from "./About";
import Contact from "./Contact";

Step 2 Adding routes

To set up the route for the Homepage, we use path. Here, we use / to define the path of the home page.

const App = () => {
  return (
    <Router>
        <Route path='/'>
          <Home />
        </Route>
    </Router>
  );
};

Then, we need to add two new routes, About and Contact:

const App = () => {
  return (
    <Router>
        <Route path='/'>
          <Home />
        </Route>
        <Route path='/about'>
          <About />
        </Route>
        <Route path='/contact'>
          <Contact />
        </Route>
    </Router>
  );
};

Step 3 Adding exact keyword

Now, if we navigate to /about or /contact page, it will display the Homepage content as well.

Why?

With React Router, if the path matches, it will display both components.

To fix that, we need to use keyword exact, so the Homepage route will be rendered only if it matches the full path.

<Route exact path='/'>
    <Home />
</Route>

Putting it all together

import React from 'react';

// react router
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

// Import pages
import Home from './Home';
import About from './About';
import Contact from './Contact';

const App = () => {
  return (
    <Router>
        <Route exact path='/'>
          <Home />
        </Route>
        <Route path='/about'>
          <About />
        </Route>
        <Route path='/contact'>
          <Contact />
        </Route>
    </Router>
  );
};

VI. Switch

The <Switch /> component will only render the first route that matches/includes the path.

Therefore, to enhance our routing, we wrap our routes with Switch

import React from 'react';

// react router
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

// Import pages
import Home from './Home';
import About from './About';
import Contact from './Contact';

const App = () => {
  return (
    <Router>
      <Switch>
        <Route exact path='/'>
          <Home />
        </Route>
        <Route path='/about'>
          <About />
        </Route>
        <Route path='/contact'>
          <Contact />
        </Route>
      </Switch>
    </Router>
  );
};

VII. Redirecting to a 404 page

With our current setup, if user navigates to a nonexist page, it will just show an empty page.

It will be a better user experience if there is an 404 announcement to notify our users.

Step 1: Create an Error.js component

We add a “Back home” button for user with <Link />.

To do that, we import <Link /> from react-router-dom:

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

const Error = () => {
  return (
    <div>
      <h1>Error Page</h1>
      <Link to='/' className='btn'>
        Back Home
      </Link>
    </div>
  );
};

export default Error;

Step 2: Import Error component

import Error from './Error';

Step 3 Add the following code so non-exist pages will route to error page

<Route path='*'>
    <Error />
</Route>

Putting it all together

import React from 'react';

// react router
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

// Import pages
import Home from './Home';
import About from './About';
import Contact from './Contact';
import Error from './Error';

const App = () => {
  return (
    <Router>
      <Switch>
        <Route exact path='/'>
          <Home />
        </Route>
        <Route path='/about'>
          <About />
        </Route>
        <Route path='/contact'>
          <Contact />
        </Route>
        <Route path='*'>
          <Error />
        </Route>
      </Switch>
    </Router>
  );
};

After setting up, if we go to /hello page, it will direct to our 404 page.

In this example, we will create a navbar

Step 1: Import Navbar

To include the navbar in our page, we first import Navbar component

// Import navbar
import Navbar from "./Navbar";

Step 2: Place Navbar component inside the <Router />

import React from 'react';

// react router
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

// Import pages
import Home from './Home';
import About from './About';
import Contact from './Contact';
import Error from './Error';

// Import navbar
import Navbar from './Navbar';

const App = () => {
  return (
    <Router>
      <Navbar />
      <Switch>
        <Route exact path='/'>
          <Home />
        </Route>
        <Route path='/about'>
          <About />
        </Route>
        <Route path='/contact'>
          <Contact />
        </Route>
        <Route path='*'>
          <Error />
        </Route>
      </Switch>
    </Router>
  );
};

export default App;

Step 3: Create Navbar.js

For example, we creates a navbar with 3 pages handled by the router.

Now, instead of using a traditional link attribute <a>, we use <Link /> instead:

=> We need to import <Link /> from react-router-dom:

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

const Navbar = () => {
  return (
    <nav>
      <ul>
        <li>
          <Link to='/'>Home</Link>
        </li>
        <li>
          <Link to='/about'>About</Link>
        </li>
        <li>
          <Link to='/contact'>Contact</Link>
        </li>
      </ul>
    </nav>
  );
};

export default Navbar;

IX. URL Params And Placeholder

useParams hook helps us get the parameter passed on the URL without using the props object.

import React from 'react';

// react router
import { BrowserRouter as Router, Route, Switch, useParams } from 'react-router-dom';

// Import pages
import Home from './Home';
import About from './About';
import Contact from './Contact';
import Error from './Error';

// Import navbar
import Navbar from './Navbar';

function Blog() {
  let { slug } = useParams();
  return <div>Now showing post {slug}</div>;
}

const App = () => {
  return (
    <Router>
      <Navbar />
      <Switch>
        <Route exact path='/'>
          <Home />
        </Route>
        <Route path='/about'>
          <About />
        </Route>
        <Route path='/contact'>
          <Contact />
        </Route>
        <Route path="/blog/:slug">
          <Blog />
        </Route>
        <Route path='*'>
          <Error />
        </Route>
      </Switch>
    </Router>
  );
};

export default App;