-1

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?

Phil
  • 157,677
  • 23
  • 242
  • 245
kalculated
  • 299
  • 4
  • 19
  • Try adding `logger.log('calling');` just before `const result = await getToken(urlSuffix);`. To me it looks like you must be calling `getToken()` from some place else. – Rocky Sims Nov 08 '21 at 00:00
  • @RockySims You're right. This isn't being called, but I just CMD+F searched my entire project and this is the only place the api fetch query is being called. How is that possible ? – kalculated Nov 08 '21 at 00:07
  • Try adding `throw 'wtf';` right after `logger.debug('TOKEN: ', token);` and then in the browser console you can look at the error to see the stack trace which will tell you where `getToken()` is being called from. – Rocky Sims Nov 08 '21 at 00:13

2 Answers2

1

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 ]);
Phil
  • 157,677
  • 23
  • 242
  • 245
0

Please note that using a try...catch inside of useEffect is a bad practice (see here).

But it seems to me that you set your async/await correctly, so it really should work.

Try adding the getToken function to dependencies of your useEffect hook.

useEffect(async() => {
    try {
      const result  = await getToken(urlSuffix);
      logger.log('returned')
      setToken(result);
    } catch (error) {
      logger.debug('ERROR: ', error);
      throw error;
    }
  }, [urlSuffix, getToken]);
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Anatoly
  • 31
  • 5
  • taking out the try catch fixed my issue. – kalculated Nov 08 '21 at 00:57
  • I think you missed the point of that post you linked. The `try..catch` isn't the problem, using an async function for the `useEffect` callback is – Phil Nov 08 '21 at 01:00
  • @kalculated there is literally no way that removing the `try..catch` fixes your issue – Phil Nov 08 '21 at 01:07
  • @Phil I also changed all my useEffects that used an async function - thanks for the answer and for helping me improve! – kalculated Nov 08 '21 at 01:09