I wish to conditionally include authenticated routes on the routing index of my ReactJS application based on whether a token exists in the user’s local storage. However, for this to work, the routes must be reevaluated on login before redirecting.
Here is the ideal usage scenario:
When the user logs in (handled by the handleLogin function), a token is set in the browser’s local storage, then the user is redirected to "/dashboard".
The ternary operator in router conditionally includes private pages in the accepted routes, intended for letting authenticated users into their dashboard, for instance.
The problem:
It appears that the routes are not updated between the time the token is set and the time the user is redirected. This means that, after a user logs in, they are met with an error because the dashboard is not a valid path yet (even though it should be).
Relevant code snippets:
In LoginPage.jsx:
const handleLogin = () => {
console.log(
`Sending login request to ${process.env.REACT_APP_API_URL}/api/auth`,
);
fetch(`${process.env.REACT_APP_API_URL}/api/auth`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email, password }),
})
.then((response) => response.json())
.then((data) => {
if (data.message === "success") {
// the login was successful
setToken(data.token);
console.log("successful login");
navigate("/dashboard");
// window.alert("The login was successful");
// get value of token using useAuth
} else {
window.alert(
`The login failed with the following error:nn${data.error}`,
);
}
})
.catch((error) => {
console.error("Could not login: ", error);
window.alert("An error occurred while trying to login.");
});
};
In index.jsx:
const Routes = () => {
const { token } = useAuth();
const [ isAuthenticated, setIsAuthenticated ] = useState(!!token);
useEffect(() => {
setIsAuthenticated(!!token);
}, [token])
// route configurations go here
const routesAuthenticated = [
{
path: "/",
element: <ProtectedRoute />,
children: [
{
path: "/",
element: <UserDashboardPage />
},
{
path: "/dashboard",
element: <UserDashboardPage />
},
{
path: "/logout",
element: <LogoutPage />
},
]
}
];
const routesUnauthenticated = [
{
path: "/",
element: <LandingPage />
},
{
path: "/login",
element: <LoginPage />
},
{
path: "/about",
element: <AboutPage />
},
{
path: "/ipsum",
element: <IpsumPage />
}
];
// decide which routes are available to user based on authentication status
const router = createBrowserRouter([
// we use the ... operator to combine these arrays into one
...routesUnauthenticated,
...(isAuthenticated ? routesAuthenticated : [])
]);
// provide configuration using RouterProvider
return <RouterProvider router={router} />;
};
Attempted fix:
I tried to use the following code to force the routes to reload on login
useEffect(() => {
setIsAuthenticated(!!token);
}, [token])
Unfortunately, this does not guarantee that the routes are reloaded before handleLogin redirects the user to their dashboard.


