Implementing client-side routing  with React Router
Tags: react, webdev, beginners
Published: 2021-05-03 20:03:06

If you decide to use React for your application, you will likely be building a Single Page Application(SPA). As your application grows, you will want your app to have multiple URLs that contain different components. This is where client-side routing comes in.

The major benefit of client-side routing is speed. Using client-side routing, **the whole application is loaded on the first `GET` request**. Because of this, it can take a while when the application first mounts, but then **we don't have to wait for a round trip server call for each page change** after that.

[React Router](https://reactrouter.com/) is the most popular routing library for React. It allows you to create intuitive routes that are human-readable so it will be easy to manage the application structure.

I am going to walk you through how to implement client-side routing in a React application using React Router step by step. 

#Installation#
In your application, run this:
```bash
$ npm install --save react-router-dom
```
Or, if you are using yarn, run:
```bash
yarn add react-router-dom
```

#Implementation#
###Add routes###
Let's first create the `<Home>` page and add `/home` routes in our application so we can go to `http://localhost:3000/home` to see the `<Home>` page.

Here is our simplest `<Home>` page:
```jsx
// myapp/src/components/Home.js

import React from 'react'

const Home = () => {
  return (
    <>
      <h1>Home page</h1>
      <h3>Welcome to my app!</h3>
    </>
  )
}

export default Home
```
Now, in `App.js`, let's set up a route to load the `Home` component:
```jsx
// myapp/src/App.js

import React from 'react'
import { BrowserRouter, Route } from 'react-router-dom'
import Home from './components/Home'

const App = () => {
  return (
    <>
      <h1>My App</h1>
      <BrowserRouter>
        <Route path="/home" component={Home} />
      </BrowserRouter>
    </>
  )
}

export default App
```
![home page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/su2n53pqysqibqo4sa81.png)
Great! The `<BrowserRouter>` component creates a base router and the `<Route>` component configures each route and specifies the component that should render.

Let's also create `<AboutUs>` and `<Contact>` pages and add `/about` and `/contact` routes as well:
```jsx
// myapp/src/components/AboutUs.js

import React from 'react'

const AboutUs = () => {
  return (
    <h1>About us</h1>
  )
}

export default AboutUs
```
```jsx
// myapp/src/components/Contact.js

import React from 'react'

const Contact = () => {
  return (
    <h1>Contact page</h1>
  )
}

export default Contact
```
```jsx
// myapp/src/App.js

import React from 'react'
import { BrowserRouter, Route } from 'react-router-dom'
import Home from './components/Home'
import Contact from './components/Contact'
import AboutUs from './components/AboutUs'

const App = () => {
  return (
    <>
      <h1>My App</h1>
      <BrowserRouter>
        <Route path="/home" component={Home} />
        <Route path="/about" component={AboutUs} />
        <Route path="/contact" component={Contact} />
      </BrowserRouter>
    </>
  )
}

export default App
```
![about us](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x0hilyn26oavvljofk3u.png)
![contact](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yvuj2hjpkl8z6uaekphi.png)

###Exact path###
![exact path](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5d91ugstv5z77e6thah.png)
Hmmm, this is not exactly what we want. We want to show `<Contact>` page only when we go to `/contact`. In this case, we can use the `exact` attribute:
```jsx
// myapp/src/App.js

import React from 'react'
import { BrowserRouter, Route } from 'react-router-dom'
import Home from './components/Home'
import Contact from './components/Contact'
import AboutUs from './components/AboutUs'

const App = () => {
  return (
    <>
      <h1>My App</h1>
      <BrowserRouter>
        <Route path="/home" component={Home} />
        <Route path="/about" component={AboutUs} />
        <Route exact path="/contact" component={Contact} />
      </BrowserRouter>
    </>
  )
}

export default App
```
![exact path](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dqaxfzwcipan4mffy005.png)
Great! Now `/contact/something` path doesn't render `<Contact>` component.

###Use `<Switch>` to set up exclusive routes###
What if you change your mind and you want to add `home/about` instead of `/about`? Sure, we can do that. But first, you need to know how `<Switch>` works.

`<Switch>` works as the `switch` statement in JavaScript. It checks the path, and, as soon as it finds a match, it breaks out of the block. Let me show you what would be a problem without using `<Switch>`:
```jsx
// myapp/src/App.js

import React from 'react'
import { BrowserRouter, Route } from 'react-router-dom'
import Home from './components/Home'
import Contact from './components/Contact'
import AboutUs from './components/AboutUs'

const App = () => {
  return (
    <>
      <h1>My App</h1>
      <BrowserRouter>
        <Route path="/home" component={Home} />
        <Route path="/home/about" component={AboutUs} />
        <Route exact path="/contact" component={Contact} />
      </BrowserRouter>
    </>
  )
}

export default App
```
![nested route](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mf9b4s4kuk5vpp7vtakb.png)
Oh no. Why do we see the `<Home>` component too? This happens because of the way JavaSript matches strings.
```bash
> "/home".match("/home/about")
null
```
If I match `/home` with `/home/about`, it returns `null`. On the other hand, if I match `/home/about` with `/home`:
```bash
> "/home/about".match("/home")
[ '/home', index: 0, input: '/home/about', groups: undefined ]
```
I get a truthy value. This is why `/home/about` renders both `<Home>` and `<AboutUs>` components. We can avoid this using `<Switch>` because it breaks after the first match found. Don't forget to put the most specific routes first and more general routes second since `<Switch>` matches from the top.
```jsx
// myapp/src/App.js

import React from 'react'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import Home from './components/Home'
import Contact from './components/Contact'
import AboutUs from './components/AboutUs'

const App = () => {
  return (
    <>
      <h1>My App</h1>
      <BrowserRouter>
        <Switch>
          <Route path="/home/about" component={AboutUs} />
          <Route path="/home" component={Home} />
          <Route exact path="/contact" component={Contact} />
        </Switch>
      </BrowserRouter>
    </>
  )
}

export default App
```
![home about](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xr3a340iiaya1ze3cwvi.png)
Perfect!
***
In the next article, I will introduce how to set up routes with parameters using React Router.