I am trying to implement a private route towards my application, and while it correctly reaches the private route when authenticated, it redirects it to the login page rather than the children. I’ve tried every solution on stackoverflow but they don’t seem to work. It’s strange because it reaches the right path (I print to console whenever I reach the private route) but it’s not able to redirect the page correctly.
PrivateRoute
import { useState, useEffect } from 'react';
import { useRef } from 'react';
import { Outlet, Navigate, useLocation } from 'react-router-dom';
import Axios from "axios";
import Cookies from "universal-cookie";
export default function ProtectedRoute({ children }) {
const [isAuthenticated, setIsAuthenticated] = useState();
// add loading state, initially true for initial render
const [isLoading, setIsLoading] = useState(true);
const checkAuth = async () => {
const cookie = new Cookies();
setIsLoading(true); // <-- set true when starting auth check
try {
if (cookie.get("stytch_session") == null) {
console.log("no cookies!")
setIsAuthenticated(false);
} else {
Axios.post(
"http://localhost:5001/test",
{},
{ headers: { sessiontoken: cookie.get("stytch_session") } }
)
.then((response) => {
console.log("reaching private route!")
setIsAuthenticated(true);
})
.catch((err) => {
console.log(err)
setIsAuthenticated(false);
});
}
} finally {
setIsLoading(false); // <-- clear loading state when completed
}
};
useEffect(() => {
checkAuth();
}, []);
if (isLoading) {
return <div className="">Loading...</div>;
}
return isAuthenticated ? children : <Navigate to={"/login"} />;
}
And here is the code snippet that’s called in app.js
<Route
path="/scroll"
element={(
<ProtectedRoute>
<Scroll />
</ProtectedRoute>
}
/>
3
Answers
Could you try using Outlet if your private route is child of
ProtectedRoute
component? Like following.Try removing the finally and putting in
What it looks like to me is that your state updates are being batched or resolving in the wrong order. This will ensure that isLoading remains true until isAuthenticated has a real value.
The
axios.post
starts an asynchronous Promise chain that the synchronous code around it doesn’t wait for. Thefinally
block is executed prior to the POST request resolving.The code should
await
the Promise to resolve.