0

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>
  );
}
1
  • Use the useEffect hook to make the call and store the result in a state by using the useState hook. Make your component render a loading indicator of some kind until the result exists in the state. Commented Jan 25, 2022 at 0:27

2 Answers 2

1

You need to set your validateToken function as an asynchronous function by adding the async keyword:

(also it is not mandatory since you didn't use await as it was pointed out in the comments).

export async function validateToken(token) {
    const requestOptions = {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json',
            Authorization: 'Bearer ' + token,
        },
    };
    const response = await fetch('/api/validateToken', requestOptions);
    return 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>
    );
  }
Sign up to request clarification or add additional context in comments.

2 Comments

Making the function async is pointless when there is no await inside the function body. It's already returning a promise so it makes no difference. Alternatively, if the function is made async, then the promise should be awaited instead of returned, i.e: return (await fetch("/api/validateToken", requestOptions)).ok;
Thanks, good catch, I edited the answer.
0

From where you get the token?

Anyways, two main things you can do:

  • create a isTokenValid Boolean using use state:
[isTokenValid, setIsTokenValid] = useState(false):
  • create a useEffectHook that will do the validation once the app component renders/ token is changing
useEffect(async ()=> {
if(!!token) {
const isValid = await validateToken(token);
setIsTokenValid(isValid);
};
}, [token]);

Hope I helped ^^

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.