Search code examples
javascriptfetch-apiuse-effect

API Query fetch works, doesn't return result though


I am trying to fetch a value from an API useEffect:

useEffect(async() => {
    try {
      const result  = await getToken(urlSuffix);
      logger.log('returned')
      setToken(result);
    } catch (error) {
      logger.debug('ERROR: ', error);
      throw error;
    }
  }, [urlSuffix]);

The thing is, the token never gets returned by the function, but the fetching part works correctly (I am logging the token). Here is the api fetch:

export const getToken = async (
  urlSuffix
) => {
  try {
    const url = `https://api_url/api/v1/asset/${urlSuffix}`;
    const data = await fetch(url, {
      headers: {
        'Accept': 'application/json',
        'X-Api-Key': API_KEY,
      },
      method: 'get',
      timeout: 5000, // 5 secs
    });

    const token = data?.data?.collection?.token;

    logger.debug('TOKEN: ', token);

    return token;
  } catch (error) {
    logger.debug('TOKEN FETCH ERROR');
  }
};

The logger.debug when fetching logs the correct token, but the logger.log in useEffect never logs that the results have returned. What is stopping getToken from returning token?


Solution

  • You seem to be using fetch() as if it were Axios which it is not.

    fetch() returns a promise that resolves with a Response object which does not have a data property. I think what you want in your getToken() function is this...

    export const getToken = async (urlSuffix) => {
      const url = `https://api_url/api/v1/asset/${urlSuffix}`;
    
      // FYI - fetch does not support timeouts
      const res = await fetch(url, {
        headers: {
          'Accept': 'application/json',
          'X-Api-Key': API_KEY,
        },
        method: 'GET',
      });
    
      if (!res.ok) {
        logger.debug('TOKEN FETCH ERROR');
        throw new Error(`${res.status}: ${await res.text()}`)
      }
    
      const data = await res.json() // parse the response stream as JSON
      const token = data.collection.token;
    
      logger.debug('TOKEN: ', token);
    
      return token;
    }
    

    You should also not pass an async function to useEffect as it breaks the cleanup process

    useEffect(() => {
      getToken(urlSuffix).then(setToken)
    }, [ urlSuffix ]);