I’m encountering an issue in my React application where I make an API call to a sign-in endpoint. The response from the API returns correctly, indicating successful authentication. However, I’m facing two problems:
The apiData and isAuth states are not updating in time, causing the navigation to the sign-in page to occur before these states are updated.
Consequently, the application navigates to the sign-in page too quickly, without waiting for the state updates.
useApi hook
import axios, { AxiosResponse } from "axios";
import { useEffect, useRef, useState } from "react";
const useApi = <T,>(url: string, method: string, payload?: T) => {
const [apiData, setApiData] = useState<AxiosResponse>();
const [loading, setLoading] = useState(false);
const [error, setError] = useState();
useEffect(() => {
const getData = async () => {
try {
const response = await axios.request({
params: payload,
method,
url,
});
setApiData(response.data);
} catch (e) {
setError(e.message);
} finally {
setLoading(true);
}
};
getData();
}, []);
return { apiData, loading, error };
};
export default useApi;
this is the form
import { useState } from "react";
import { useNavigate } from "react-router-dom";
export const SignIn = () => {
const [userInfo, setUserInfo] = useState({
user: "",
password: "",
});
const navigate = useNavigate();
const submitForm = (e) => {
e.preventDefault();
navigate("/user/sign-in", { state: userInfo });
};
const updateUser = (newVal: string) => {
setUserInfo((prev) => ({
...prev,
user: newVal,
}));
};
const updatePassword = (newVal: string) => {
setUserInfo((prev) => ({
...prev,
password: newVal,
}));
};
return (
<form onSubmit={(e) => submitForm(e)}>
<label>username</label>
<input type="text" onChange={(e) => updateUser(e.target.value)} />
<label htmlFor="">password</label>
<input type="password" onChange={(e) => updatePassword(e.target.value)} />
<button type="submit">submit</button>
</form>
);
};
privateRoute where I check if user is auth or not
import { useEffect, useState } from "react";
import useApi from "../../api/useApi";
import { Navigate, useLocation } from "react-router-dom";
import UserDashboard from "./UserDashboard";
export const PrivateRoute = () => {
const location = useLocation();
const { apiData, loading, error } = useApi(
import.meta.env.VITE_SIGN_IN,
"GET",
location.state,
);
const [isAuth, setAuth] = useState<boolean>(false);
useEffect(() => {
if (apiData?.status === 200) {
console.log(apiData, "api apiData");
setAuth(true);
}
}, [apiData]);
return (
<>
{isAuth ? (
<UserDashboard />
) : (
<Navigate to="/sign-in" state={{ from: location.pathname }} />
)}
</>
);
};