Programmatic Navigation in React using react-router
Tags: react, javascript, webdev, tutorial
Published: 2019-11-28 23:24:10

I have seen my fair share of react tutorials, but any time that they talk about navigation using react-router, they only show the way using the Link component. As soon as someone starts working on his/her own project, one of the first problems they come across is how to route programmatically, which basically means routing with ways other than clicking on something wrapped inside a \<Link> component.
This blog mainly aims to be a refuge to those people who come here looking for the answers to this problem.

****************

##1. \<Redirect> Component

We can redirect using \<Redirect> component by simply passing the route we want to redirect to and rendering the component. It already comes loaded in the react-router-dom library.

```javascript
import { Redirect } from "react-router-dom";
```
The easiest way to use this method is by maintaining a redirect property inside the state of the component.

```javascript
state = { redirect: null };
render() {
  if (this.state.redirect) {
    return <Redirect to={this.state.redirect} />
  }
  return(
  // Your Code goes here
  )
}
```
Whenever you want to redirect to another path, you can simply change the state to re-render the component, thus rendering the \<Redirect> component.
```javascript
this.setState({ redirect: "/someRoute" });
```
**Note**
This is the recommended way to navigate other than the \<Link> method.
Discussed in detail towards the end of the post.


The downside of this method is that in cases like when we want to redirect directly from a redux action, we cannot do so. 

****************
##2. useHistory Hook

As of release 5.1.2, react-router ships with some new hooks that can help us access the state of the router.

For now, we only need to talk about the useHistory hook.

```javascript
import { useHistory } from "react-router-dom";

function App() {
  let history = useHistory();
}
```

After this, we can use the .push() method to redirect to any route we want.

```javascript
history.push('/someRoute')
```
*****************

##3. History prop

Every component that is an immediate child of the \<Route> component receives history object as a prop. This is the same history (library) which keeps history of the session of React Router. We can thus use its properties to navigate to the required paths.

```javascript
this.props.history.push("/first");
```

A common problem that we can encounter here is that in components which are not an immediate child to the \<Route> component, there is no history prop present. This can be easily solved using the withRouter function.

###3.1. withRouter

withRouter is a function provided in the react-router-dom library that helps us access the history prop in components which are not immediate children to the \<Route> components.
To import withRouter

```javascript
import { withRouter } from "react-router-dom";
```

Now to get the history prop inside our component, we need to wrap our component with withRouter while exporting it.

```javascript
export default withRouter(yourComponent);
```
We can now access the history prop same as above to do our required navigations.

************
##4. createHistory

The methods we learned above can cover most of the cases that we'll ever encounter while building a react app, so why this fourth method?
Every time we need to redirect from, say as an example a redux action, we always have to pass history to the action, unnecessarily increasing the number of arguments. This method can thus be used to get a neater code.

In this method, we make our custom history instance which we can import in other files to redirect.

```javascript
// Inside /utils/history.js
import createHistory from "history/createBrowserHistory";
export default createHistory();
```

As \<BrowserRouter> uses its own history and does not accept any outer history property, we have to use \<Router> instead of it.

```javascript
import { Router } from "react-router-dom";
import history from "./utils/history";

function App(){
  return(
    <Router history={history}>
    // Your Routes go here
    <Router>
  )
}
```

After this, we can import this history instance in whichever file we want to redirect from.

```javascript
import history from "./utils/history";

history.push("/somePath");
```

**************
##NOTE
At its core, React is a declarative approach to building UIs.

Declarative approach is one where we express the logic of a computation without describing its control flow, or without describing what's actually happening behind the scenes.

Due to this reason, the recommended way to navigate other than \<Link> is using \<Redirect> component.

There is no harm in using the other methods mentioned here, just that they don't exactly align with React's vision.

***************
##Repository
A fully working implementation of the above methods is available on my Github profile. Feel free to explore it if anyone wants to see these methods actually working in a project.

{% github https://github.com/projectescape/blogs-reference %}

 
*********