0

I have an application with dynamic tabs that show different tabs depending if the user is authenticated or not. Naturally, I have created a PrivateRoute component to protect against users accessing certain pages while unauthenticated. However, I've discovered if the user logs in, visits an authenticated page, and then logs out, the PrivateRoute is still triggered even though the component no longer exists in DOM.

This is a problem because now that the user is not authenticated, the PrivateRoute still triggers and Redirects to the auth URL (which is the fallback for unauthenticated users in the PrivateRoute component).

Video example: https://streamable.com/qviin2

Code reproduction: https://codesandbox.io/s/pensive-voice-1w3rc?file=/src/App.tsx

Steps to reproduce:

  • Visit the Log In Tab
  • Click Log In
  • Click Tab 2
  • Click Log Out
  • Observe how you are unable to click to change any tab and how the private route is still triggered when changing tabs in the console.

(Also it's interesting to note that the Tab2 page shows, but the URL is incorrect and the tab that you click on doesn't change)

Any guidance on how to remove private routes from a router stack after logout (without a page refresh) would be GREATLY appreciated!! Thanks.


Here's my PrivateRoute:

const PrivateRoute: React.FC<PrivateRouteProps> = ({
  component: Component,
  ...rest
}) => {
  const { user, loading } = useAuth();

  console.log("PRIVATE ROUTE [LOADING]", loading);

  return (
    <Route
      {...rest}
      render={(props) => {
        return (
          <>
            {loading ? (
              <Loading />
            ) : user ? (
              <Component {...props} />
            ) : (
              <Redirect
                to={{
                  pathname: `/auth`,
                  state: {
                    from: props.location.pathname
                  }
                }}
              />
            )}
          </>
        );
      }}
    />
  );
};

My App.tsx contains the following routes:

<Route exact path="/tab2" component={Tab2} />
<Route path="/:tab(auth)" component={Login} exact />
<PrivateRoute path="/:tab(account)" component={Account} />
<PrivateRoute
  path="/:tab(account)/settings"
  component={Settings}
  exact
/>
<Route exact path="/">
  <Redirect to="/tab1" />
</Route>

On login I call an AuthProvider method to set a Userobject and route to aPrivateRoute`:

<IonButton
  disabled={loading}
  onClick={async () => {
    await onAuthenticate();
    push("/account");
  }}
>
  Log In
</IonButton>

And on Logout, I set the User object to undefined using the AuthProvider and try to route away from the PrivateRoute:

<IonButton
  onClick={async () => {
    await onLogout();
    push("/tab2");
  }}
>
  Log out
</IonButton>
Jordan Lewallen
  • 1,681
  • 19
  • 54
  • you need to take a look at this stackoverflow question to explain what is happening - https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately – Aaron Saunders Jun 27 '21 at 00:27
  • https://codesandbox.io/s/infallible-varahamihira-592vk?file=/src/App.tsx – Aaron Saunders Jun 27 '21 at 05:09

0 Answers0