useHistory and Redirect hooks in React

This tutorial explores the useHistory hook of react-router-dom, which is a special package of React that allows us to make our app navigation robust and efficient.

react-router-dom allows us to navigate through different pages on our app with/without refreshing the entire component. By default, BrowserRouter in react-router-dom will not refresh the entire page.

However, if you want your app to refresh on the click of any link or button, then you can set the forceRefresh attribute to true inside the BrowserRouter of react-router-dom, as follows:

<BrowserRouter forceRefresh={true} />

Let’s use npx create-react-app myapp to create a simple react app and install react-router-dom with the following command inside the terminal of our app.

npm i react-router-dom

Now, we will create a components folder in src directory of our app, and create the following three components.

  • Home.js
  • About.js
  • ContactUs.js

We will import these components in App.js in the following manner.

import React from 'react'
import './App.css';
import { BrowserRouter, BrowserRouter as Router,Redirect, Switch ,Route,Link} from 'react-router-dom';
import {Home} from './components/Home'
import {About } from './components/About'
import {ContactUs} from './components/ContactUs'
import {NotFound} from './components/NotFound'


function App() {
  return (
    <BrowserRouter>
<div className="App">
   <h1>React Router Demo</h1>
   <div className="navbar">
   <Link to="/">Home</Link>
   <Link to="/contact">Contact Us</Link>
   <Link to="/about">About</Link>
   </div>
  
   
   <Switch>
     <Route exact path="/">
       <Home />
     </Route>
     <Route path="/contact">
    <ContactUs />
     </Route>
     <Route path="/about">
       <About />
     </Route>
     <Route path="*"><NotFound /></Route>
   </Switch>
    </div>
    </BrowserRouter>
    
  );
}

export default App;

For each component, we have defined a Link that specifies the path and route. We have also defined a * path which will render the Not Found component in case a random and undefined path is defined.

Now, suppose one of the routes, e.g. ‘Contact Us’, is a protected route. Suppose we need to redirect the user to that component only if they have logged in to our app; otherwise, they will be redirected back to the homepage.

For this purpose, we will create a login button on the App.js file that will be false by default, but a click on it will login the user. We will also declare a useState hook where we will keep track of the state of the login button, as follows.

const [login,setLogin] = useState(false);
<button onClick={()=>setLogin(!login)}>{login ? "Login" : "Log out"}</button>

And in the ContactUs component, we can define the redirect path based on the value of login button, as follows.

<Route path="/contact">
{login ? <ContactUs /> : <Redirect to="/" />}
</Route>

Now, we can see that if the user is logged in, only then they can visit the Contact Us page. Otherwise, they will be redirected to the homepage.

Another way of doing this is through the useHistory hook. In the Contact Us component, we will pass the login prop. Depending on the value of login, we will let the history.push method render the correct component in the following manner.

import React from 'react'
import { useHistory, useEffect } from 'react-router-dom'

export const ContactUs = ({login}) => {
    const history = useHistory();

    useEffect(()=>{
        if(!login){
            history.push("/")
        }
},[login,history]);

    return (
        <div>
            This is the Contact Us Page
        </div>
    )
}

Also, remember to make the Contact Us route on App.js a normal route before you import useHistory in the respective component:

<Route path="/contact">
    <ContactUs login={login}/>
     </Route>

This was a simple explanation of Redirect and useHistory from React. We hope you find it useful.