Routing  using react-router-dom
Tags: react, router, nested, routing
Published: 2020-11-02 15:26:05

In this post, I will talk about routing using react-router-dom in the react applications.
But, first, question arises, Why do we need to use routing in react ? And maybe you don't know what is React ?

## What is React ?
React is a javascript framework that is developed and maintained by Facebook by providing single page applications.

### Single Page Applications (SPA)?
In the early development of web applications, whenever a user clicks on a new page link, then the client side of the browser sends data to server and grabs a particular html file related to the link and  reloads the page which takes time. 

But with implementation of SPA, user only has one index.html file and whenever user clicks on a new link, the data re-renders on the same page without grabbing the entire new html file.

## Why do we use routing in react ?
Since we are in the world of SPA, the routing helps us to display some template and hide another template based on the route.

*Okay, I hope you know understand the use of routing in SPA.*

Let's dive into the coding part of the simple project we are going to make to understand about react-router-dom.

## Create React Application
Create a new react app named routing. Run the below command in your command prompt, terminal or git bash.
`npx create-react-app routing`
`cd routing`
`npm start` or `yarn start`

By running the about commands, your project is now on the `localhost:3000`

## Installing react-router-dom

To install react-router-dom in your app, simply run `npm i react-router-dom` or `yarn add react-router-dom`.

## Folder structure
You folder structure should look like this. Delete unnecessary files.

![folder structure](https://dev-to-uploads.s3.amazonaws.com/i/7qsz99o6bupjs09jpm7f.PNG)

And make sure to remove all the content from App.css file.

## Adding New Route
Before creating a route lets make two new components, home.js and room.js

home.js should look like this.
```
import React from 'react'

export default function Home() {
    return (
        <div>
            Welcome to the Home.
        </div>
    )
}

```
room.js should look like this.
```
import React from 'react'

export default function Room() {
    return (
        <div>
            Welcome to the Room.
        </div>
    )
}
```

Next your App.js should look like this.
```
import { BrowserRouter, Route } from "react-router-dom"

import './App.css';
import Home from "./home";
import Room from "./room"

function App() {
  return (
    <div className="App">
      <BrowserRouter>
        <Route path="/" component={Home} />
        <Route path="/room" component={Room} />
      </BrowserRouter>
    </div>
  );
}

export default App;
```
#### Understanding react-router-dom terms

In the App.js, I take BrowserRouter and Route from the react-router-dom.

**BrowserRouter** is a top level components which basically lets us start using routing in our react application. So make sure that you wrap all your components inside this.

**Route**  basically, tells the react-router that components in this are going to be on different pages.So, in this case, Home and Room are the one.

Now, if you go to your browser you should see this.
![browser](https://dev-to-uploads.s3.amazonaws.com/i/twm4u6wn7jmsktvqowf3.PNG)

In your navigation, you should link to /room to visit different page template. And you should see this.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/4tqlido9vpmln1a5qssa.PNG)

Confused ??
Don't worry I will tell you why this happened.

If you see our App.js,
```
import { BrowserRouter, Route } from "react-router-dom"

import './App.css';
import Home from "./home";
import Room from "./room"

function App() {
  return (
    <div className="App">
      <BrowserRouter>
        <Route path="/" component={Home} />
        <Route path="/room" component={Room} />
      </BrowserRouter>
    </div>
  );
}

export default App;
```
You can see that "/" path represents Home component and "/room" path represents Room component.
So, when I changed the path from "/" to "/room" both Home and Room both components got rendered.
To render only one component at a time, we can use exact prop in the Route like this.
```
<Route exact path="/" component={Home} />
<Route path="/room" component={Room} />
```

And Now our localhost only renders one page at a time. Like this.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/c1vje9l1zf8g66hgf6l7.PNG)

However, we can achieve the above goal by getting the Switch from the react-router-dom.
```
import { BrowserRouter, Route, Switch } from "react-router-dom"
```
Switch make sures that only one components loads at one time.
```
import { BrowserRouter, Route, Switch } from "react-router-dom"

import './App.css';
import Home from "./home";
import Room from "./room"

function App() {
  return (
    <div className="App">
      <BrowserRouter>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/room" component={Room} />
        </Switch>
      </BrowserRouter>
    </div>
  );
}

export default App;
```

## Adding Navigation Links

Now, we need to click something so that we can change routes. For react-router gives us the Link and NavLink.
Import these into App.js.
```
import { BrowserRouter, Route, Link, NavLink } from "react-router-dom"
```
However, Behind the scenes, the Link and NavLink are simply anchor tags.
But the difference between two is that NavLink comes with a class of active whereas Link does not.

Okay, Now add links to our application.
```
import { BrowserRouter, Route, Link, NavLink } from "react-router-dom"

import './App.css';
import Home from "./home";
import Room from "./room"

function App() {
  return (
    <div className="App">
      <BrowserRouter>
        <div>
          <nav>
            <Link to="/">Home</Link>
            <NavLink to="/room">Room</NavLink>
          </nav>
          <Route exact path="/" component={Home} />
          <Route path="/room" component={Room} />
        </div>
      </BrowserRouter>
    </div>
  );
}

export default App;
```

Now if you click on different links you can navigate to different pages.

## Nested Routing

Nested Routing in the components is bit tricky to manage.But don't worry I will tell you the way which I found most easy for this and this is the way that they recommend in the react-router-dom documentation.

So, Suppose you want to have route like this "/room/room1". I mean there could be multiple rooms inside the room route.

Okay, Now , create new file called room-container.js and it should look like this:
```
import React from 'react'
import { Route, Link  } from "react-router-dom"
import Room from './room'
import RoomId from './room-id'

export default function RoomContainer(props) {
    return (
        <div>
            <Link to={`/room/${Math.random()}`}> Link to different Nested Rooms </Link>
            <div>
                <Route exact path="/room" component={Room} />
                <Route path="/room/:roomId" component={RoomId} />
            </div>
        </div>
    )
}
```

Now in your App.js, instead of importing room.js file you should import room-container.js file and in your room-container.js file you should import room.js

Oh God, I hope I didn't make it much confusing.

Your App.js file should look like:
```
import { BrowserRouter, Route, Link, NavLink } from "react-router-dom"

import './App.css';
import Home from "./home";
import RoomContainer from "./room-container"

function App() {
  return (
    <div className="App">
      <BrowserRouter>
        <div>
          <nav>
            <Link to="/">Home</Link>
            <NavLink to="/room">Room</NavLink>
          </nav>
          <Route exact path="/" component={Home} />
          <Route path="/room" component={RoomContainer} />
        </div>
      </BrowserRouter>
    </div>
  );
}

export default App;
```

Now, you might be wondering why did we follow this structure.Actually, this is the structure that the react-router-dom documentation recommends us to implement to correctly achieve nested routing.

Now, in your room-container.js, you might wondering about these lines of code,
```
<Link to={`/room/${Math.random()}`}> Link to different Nested Rooms </Link>
<Route path="/room/:roomId" component={RoomId} />
```

First line of code is the link to nested route and in the second the line ":roomId" defines that the this value is gonna be dynamically put  here. ":roomId" is know as the params for the nested route link.

Actually, this is the way we implement nested route to a component. And in this case I have created a new file called room-id.js and it should look like this:

```
import React from 'react'

export default function RoomId(props) {
    return (
        <div>
            Welcome to Room Id:   

            {
                props.match.params.roomId
            }
        </div>
    )
}

```


Now, if click on the Room and then click on to the Link to different Nested Rooms, you will be routed to the different routes.And you can see the `roomId` for it in the room-id.js component.


## Understanding terms and Some theory

Whenever you define a in the <Route /> and the component in it has props of the route which can be useful to us.
For example: In the room-id.js, I can access and display the `roomId` using the `props.match.params.roomId`.

Similarily these props are also presented in the room-container.js and to maintain consisitency in our application, most developers prefer to use them instead of hard-coding the routes like these:
```
 <Link to={`/room/${Math.random()}`}> Link to different Nested Rooms </Link>
            <div>
                <Route exact path="/room" component={Room} />
                <Route path="/room/:roomId" component={RoomId} />
            </div>
```

We can implement the same thing like this:
```
 <Link to={`${props.match.url}/${Math.random()}`}> Link to different Nested Rooms </Link>
            <div>
                <Route exact path={`${props.match.path}`} component={Room} />
                <Route path={`${props.match.path}/:roomId`} component={RoomId} />
            </div>
```

**props.match.path** represents the path that is relative to the parent container, the user is currently on.
**props.match.url** represents the matched portion of the url.

##Conclusion

We have seen how we can implement react routing in react application and also we got to know about the nested routing.

I know nested routing might seems confusing for the beginner but if you understand it by implementing it on a project you will get it.

Thanks for reading.
Happy Coding:)