3

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?

Normal
  • 1,616
  • 15
  • 39

3 Answers3

3

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.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • 1
    That's what I'm talking about!! – Normal May 15 '22 at 20:41
  • @drewreese is there a way to apply this on the `redirect` function too? At the end of my action method I have this line `return redirect('/')` How could I incorporate `replace` from your code into mine? – D. Rattansingh Jun 09 '23 at 21:51
  • @D.Rattansingh No, I don't think so. The [redirect](https://reactrouter.com/en/main/fetch/redirect) utility function is *already* a redirect, e.g. shorthand for returning a status 302 response. – Drew Reese Jun 09 '23 at 22:03
2

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.

Prajwal Kulkarni
  • 1,480
  • 13
  • 22
  • I think there must be a method provided from react-router other than having me set a state of isLoggedIn and check, right? I will make a request on their github, I saw your answer great, however, I'm not sure if this only happens to me, but it's a little bit buggy, try to play with this a little bit, like go in and out and inside something else, then logout, and when you're on the login page, hit the back arrow fast multiple times, and you'll see that you'll end up inside the app again even though you're not authurized – Normal May 15 '22 at 15:02
  • If you're facing such issues, it could likely be some mismanagement in your auth state. Make sure your state is synchronous and for such instances try using localstorage data instead dispatching an action and fetching the state from redux or context API. Has worked well for me. – Prajwal Kulkarni May 15 '22 at 16:16
-1

Try this

componentDidUpdate() {
  window.addEventListener('popstate', function(event) {
    window.history.pushState(null, document.title, window.location.href);
  });
}

You can find the complete answer here:How to prevent user from going back in react-router-dom?

Ingenious_Hans
  • 724
  • 5
  • 16
  • From MDN: *The Window.history read-only property returns a reference to the History object ... There is no way to clear the session history or to disable the back/forward navigation from unprivileged code. The closest available solution is the `location.replace() `method, which replaces the current item of the session history with the provided URL.* https://developer.mozilla.org/en-US/docs/Web/API/Window/history – Normal May 18 '22 at 18:19