I have a function which needs to submit an API request, wait for the response and return whether the status of the response was within the 200-299 range (i.e., the response.isOk attribute).
However, when I call the function from a component, I assume I get the response too late (the function doesn’t wait for the fetch to finish and instead returns undefined). Is there a way around this?
AuthFunctions.js
export function validateToken(token) {
const requestOptions = {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + token,
},
};
return fetch("/api/validateToken", requestOptions).then(
(response) => response.ok
);
}
App.js
function App() {
return (
<BrowserRouter>
<div className="App">
{!token ||
(token === "" && token === undefined) ||
!validateToken(token) ? (
<AuthPage setToken={setToken} />
) : (
<>
<Routes>
<Route
exact
path="/dashboard"
element={<Dashboard token={token} />}
></Route>
</Routes>
</>
)}
</div>
</BrowserRouter>
);
}
>Solution :
You need to set your validateToken function as an asynchronous function by adding the async keyword:
export async function validateToken(token) {
const requestOptions = {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + token,
},
};
return fetch("/api/validateToken", requestOptions).then(
(response) => response.ok
);
}
You can save the token validation status in the state and use effect to call you api on the first render.
I added a hasFetched state to avoid showing the authentification page while waiting for the api response for a better user experience. I only return a loading paragraph but what you want to return is up to you.
function App() {
const [hasFetched, setHasFetched] = useState(false);
const [isTokenValid, setIsTokenValid] = useState(false)
useEffect(()=>{
validateToken(token).then((response)=>{
setIsTokenValid(response);
setHasFetched(true);
}).catch((error)=>{
console.log(error)
setHasFetched(true);
})
},[])
if (!hasFetched) return <p>Loading</p>;
return (
<BrowserRouter>
<div className="App">
{!token ||
(token === "" && token === undefined) ||
!isTokenValid ? (
<AuthPage setToken={setToken} />
) : (
<>
<Routes>
<Route
exact
path="/dashboard"
element={<Dashboard token={token} />}
></Route>
</Routes>
</>
)}
</div>
</BrowserRouter>
);
}