I have a login page but that authenticates the login on router with a call to the backend. The backend returns a response 200 if the user is authenticated, and 400 if its not.
This is my code chunk for the private route
export default function PrivateRoute({ component: Component, ...rest }: { component: any }) {
// https://stackoverflow.com/questions/65193640/how-to-detect-jwt-token-expire-on-react
const [userLoggedIn, setUserLoggedIn] = useState(false);
useEffect(() => {
// If acess_token cannot be found, set expiration to current time to force login
const jwtToken = localStorage.getItem('sycamore_access_token')
axiosInstance.post('/auth/authenticatetoken/', {
token: jwtToken,
user: localStorage.getItem("user")
})
.then(res => {
setUserLoggedIn(true)
console.log(userLoggedIn, "A")
})
.catch(error => {
setUserLoggedIn(false)
console.log(userLoggedIn, "B")
})
}, [])
and returns the component if its authenticated
return (
<React.Fragment>
{console.log(userLoggedIn)}
<Route
{...rest}
render={(props) =>
(userLoggedIn) ? (
<Component {...props} />
) : (
<Redirect
to={{ pathname: '/Login', state: { from: props.location } }}
/>
)
}
/>
</React.Fragment>
The problem here is that the state userLoggedIn does not seem to update immediately, and returns false -> authenticated -> true, by which then it has already redirected me back to the login page again. Any idea why this is happening or how to solve this?
CodePudding user response:
The problem here is that the state userLoggedIn does not seem to update immediately
That's correct, userLoggedIn
will change once the post request returns a response.
You can add a state like loading/inProgress
and use it to show a loading component/text until the API returns a response.
const [userLoggedIn, setUserLoggedIn] = useState(false);
const [loading, setLoading] = useState(true);
useEffect(() => {
// If acess_token cannot be found, set expiration to current time to force login
const jwtToken = localStorage.getItem('sycamore_access_token');
axiosInstance
.post('/auth/authenticatetoken/', {
token: jwtToken,
user: localStorage.getItem('user'),
})
.then((res) => {
setUserLoggedIn(true);
console.log(userLoggedIn, 'A');
})
.catch((error) => {
setUserLoggedIn(false);
console.log(userLoggedIn, 'B');
})
.finally(() => {
setLoading(false);
});
}, []);
Now you can return early if loading
is true. This will prevent the redirect check until loading
changes to false.
if(loading) return <p>Loading...</p>
return (<React.Fragment>...);