This is the private route component, and before users access the page I need to check if they are logged in (if their token is valid)
import { authService } from '../authservice/AuthService';
export default function PrivateRoute({ children }: { children: JSX.Element }) {
//const isLoggedIn = authService.isLoggedIn();
let location = useLocation();
if (!isLoggedIn) {
return <Navigate to="/login" state={{ from: location }} />;
}
return children;
}
This is the function I’m trying to call inside the PrivateRoute component
class AuthService {
api_domain = "http://localhost:5000"
async isLoggedIn() {
if (!this.getToken() || typeof this.getToken() != 'string') {
return false
}
axios.get(this.api_domain + "/", {headers: {Authorization: this.getToken()}})
.then(res => {
if (res.data.status === 'ok') {
return true
}
return false
})
}
}
>Solution :
The reason the isLoggedIn function needs to be async is because it makes a request to your server, something which actually takes time. Therefore, what you want to be doing is displaying some sort of loading state until the user has been verified by the server.
You can create a custom hook which returns two states, isLoading and isLoggedIn, initializing isLoading as true:
export function useIsLoggedIn() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const token = getToken();
if (!token || typeof token !== 'string') {
setIsLoading(false);
return;
}
axios.get(api_domain + "/", {headers: {Authorization: token}})
.then(res => {
if (res.data.status === 'ok') {
setIsLoggedIn(true);
}
setIsLoading(false);
})
.catch(() => setIsLoading(false));
}, []);
return { isLoggedIn, isLoading };
}
Then, in your PrivateRoute component, you can use this to ensure that the verification has already happened:
export default function PrivateRoute({ children }: { children: JSX.Element }) {
const { isLoggedIn, isLoading } = useIsLoggedIn();
const location = useLocation();
if (isLoading) {
return <div>Loading...</div>; // or some other loading state
}
if (!isLoggedIn) {
return <Navigate to="/login" state={{ from: location }} />;
}
return children;
}