Home > Software engineering >  Returning value instead of promise in useEffect in React
Returning value instead of promise in useEffect in React

Time:12-06

I have the following code,

let currencyValues = [];

const retrieveCurrencyPairs = async (pair) => {
    const r = await fetch(pair.url);
    const rParsed = await r.json();
    let newCurrencyValue = { currency: pair.countries, value: rParsed };
    return newCurrencyValue;
};

useEffect(() => {
    currencyValues = currencyPairs.map(retrieveCurrencyPairs);
    console.log(currencyValues);
}, []);

and the following expectations:

  • On page load, the useEffect triggers the function inside of the map()
  • For each value of the array, the retrieveCurrencyPairs() is triggered and awaits for the result, which is then returned
  • The currencyValues array is the filled with the 3 new objects

Unfortunately the function is returning promises, instead of the objects.

Any tip on how to return the objects instead?

CodePudding user response:

async functions always return promises. You could do this instead:

Promise.all(currencyPairs.map(retrieveCurrencyPairs))
  .then( results => ... )

Promise.all has the additional benefit of running them all in parallel instead of sequentially.

You might consider Promise.allSettled if you want to deal with individual failures/rejections without rejecting the whole list.

CodePudding user response:

I think you should use Promise.all in order to properly handle multiple promises

useEffect(() => {
    (async()=>{
        const results = await Promise.all(currencyPairs.map(retrieveCurrencyPairs))
        console.log(results );
    })()
}, []);

OR

useEffect(() => {
   const results = Promise.all(currencyPairs.map(retrieveCurrencyPairs)).then(results => console.log(results));     
}, []);

To learn more about Promise.all or To learn more about Promise.allSettled use MDN

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled

CodePudding user response:

Try this

  useEffect(() => {
    (async()=>{
        currencyValues = await currencyPairs.map(retrieveCurrencyPairs);
        console.log(currencyValues);
    })()
    }, []);

CodePudding user response:

In the code you provided, retrieveCurrencyPairs is an async function, which means that it returns a promise that resolves to the return value of the function. This means that currencyValues will be an array of promises, rather than an array of objects.

To fix this, you can use the await keyword inside of the map function to wait for the promises to resolve before assigning the result to currencyValues. You will also need to make the useEffect function async so that you can use await inside of it. Here's an example of how you could do this:

const retrieveCurrencyPairs = async (pair) => {
    const r = await fetch(pair.url);
    const rParsed = await r.json();
    let newCurrencyValue = { currency: pair.countries, value: rParsed };
    return newCurrencyValue;
};

const useEffect = async (() => {
    currencyValues = await Promise.all(currencyPairs.map(retrieveCurrencyPairs));
    console.log(currencyValues);
}, []);

This code will wait for all of the promises returned by retrieveCurrencyPairs to resolve before assigning the result to currencyValues. This means that currencyValues will be an array of objects, rather than an array of promises.

CodePudding user response:

async functions always return promises even implicitly. You need to either await the currency.Pairs.map(retrieveCurrencyPairs) either .then it

Since a Promise.all answer is already posted and is a good practice to stick with one approach, here is the alternative with await

useEffect(() => {
    const getCurrencyValues = async ()=>{
    const currencyValues = await currencyPairs.map(retrieveCurrencyPairs);
    return currencyValues
    }
    console.log(getCurrencyValues());

}, []);
  • Related