How to prevent user from going back in react-router v6?

Viewed 1197

I'm using react-router-dom for routing in my ReactJS app. And I want to prevent a user from going back after login i.e I don't want the user to go back again on the login screen when he hit the back button on the browser after login.

or another example is when the user clicks the logout button, I don't want the user to be able to navigate back to the main app after logging out.

Most of the other questions I was able to find are obsolete and no longer usable for react-router v6.

Maybe I want to remove the object from the history of react-router-dom somehow?

I think there must be a method provided from react-router other than having me to set a state of isLoggedIn and check, right?

3 Answers

You can create a different set of routes based on a condition(e.g: user logged in or not) and then have a default redirect route for each condition. For creating this set, you'll have to know what routes are accessible under what states, for instance, an unauthorized user cannot navigate to routes that include any create, delete, or update actions, if a user tries to access such routes they should be redirected to a default route like a login page. Similarly, an authorized user should not be able to access login/signup routes. You can structure your code like below, this is with regards to auth state, but you are free to use any other conditions as well:

In your main component(typically App.js/App.tsx where you define your routes)

let routes;
if(loggedIn){
    
    routes = (
      <Routes>
          <Route path='/' element={<HomePage/>}/>
          <Route path='/groups' element={<Groups/>}/>
          <Route path='/some/other/route/:id' element={<AuthCompN/>}/>
          <Route path='*' element={<Navigate to ='/'/>}/>
      </Routes>
    )
  }
  else{
      routes = (
      <Routes>
        <Route path='/auth' element={<Login/>}/>
        <Route path='*' element={<Navigate to="/auth"/>}/>
      </Routes>
    )
  }

  return (
    <BrowserRouter>
      <div className="fixed w-full h-full">
        {isLoggedIn&&<Navbar />}

        {routes}
        

      </div>
    </BrowserRouter>
  );

As we can see, the variable routes is assigned different set of routes based on the login state. The last route whose path is marked * is any other path other than the ones defined above it, so if a user is logged in and tries to access or go back to /login path, they are redirected to the route that renders home component or something similar. Same logic applies when a user is not logged in and tries to access protected routes.

Don't change the default browser back button behavior. If you don't want to allow a user to navigate back to a login page after successfully authenticating, then use a redirect to REPLACE the current entry on the history stack instead of PUSHing a new entry.

Example:

const navigate = useNavigate();

...

const loginHandler = () => {
  ... authentication business logic ...

  // if authenticated
  navigate(targetPath, { replace: true }); // redirect!!!
};

From here, if a user presses the back button or issues a back navigation they will navigate back to the path they were on prior to navigating to the login path.

This is in fact the standard convention for handling protected routes and authentication. See How to create a protected route.

Related