Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolve promise.all inside a useEffect

I have a simple useEffect in my component to fetch data from 3 API calls:

  useEffect(() => {
    Promise.all([
      fetch(`${baseUrl}/counts?entity=color`),
      fetch(`${baseUrl}/counts?entity=brand`),
      fetch(`${baseUrl}/counts?entity=category`)
    ]).then(([x, y, z])=> {
        console.log(x.json(), y.json(), z.json());
      });
  }, []);

I'm expecting the actual data I get from the API so that I can use it in my UI, but instead I'm getting this: enter image description here

I've also tried doing this:

  useEffect(() => {
    Promise.all([
      fetch(`${baseUrl}/counts?entity=color`),
      fetch(`${baseUrl}/counts?entity=brand`),
      fetch(`${baseUrl}/counts?entity=category`)
    ]).then(responses => responses.map(r => r.json()))
      .then(([x, y, z])=> {
        console.log(x, y, z);
      });
  }, []);

I see the desired value inside PromiseResult, but I'm not sure how to extract it: enter image description here

What am I doing wrong here. How do I access the array in my code?

like image 741
Amol Borkar Avatar asked Feb 06 '26 01:02

Amol Borkar


2 Answers

The issue is that .json returns another promise, so you'd need to call .then on it to get the eventual value. Or since you're doing multiple, you'd need to combine it with Promise.all, and then call .then on that.

One possibility is to tweak your .map attempt so that it has an additional Promise.all:

Promise.all([
  fetch(`${baseUrl}/counts?entity=color`),
  fetch(`${baseUrl}/counts?entity=brand`),
  fetch(`${baseUrl}/counts?entity=category`)
]).then(responses => {
  return Promise.all(responses.map(r => r.json()))
})
.then(([x, y, z])=> {
  console.log(x, y, z);
});

But that does have the downside that all of the fetches must get far enough along that they resolve, before any of them can call .json. This may slightly delay finishing things. So another possibility is to set up all of the work up front, and only call Promise.all with those final promises.

Promise.all([
  fetch(`${baseUrl}/counts?entity=color`).then(val => val.json()),
  fetch(`${baseUrl}/counts?entity=brand`).then(val => val.json()),
  fetch(`${baseUrl}/counts?entity=category`.then(val => val.json()))
]).then(([x, y, z])=> {
  console.log(x, y, z);
});

With that version, each of the fetches will go at whatever pace it can manage, and will convert itself to json as soon as it can. Then once all of them are finished, the combined promise resolves.

like image 151
Nicholas Tower Avatar answered Feb 07 '26 13:02

Nicholas Tower


You could combine your all fetch call and map() to generate an array of promises to easily loop the data:

const baseUrl = "https://jsonplaceholder.typicode.com";

  useEffect(() => {
    const urls = [`${baseUrl}/todos/1`, `${baseUrl}/todos/2`, `${baseUrl}/todos/3`];

    const fetchData = async () => {
      try {
        const responses = await Promise.all(urls.map(url => fetch(url)));
        const data = await Promise.all(responses.map(response => response.json()));
        console.log(data);
      } catch (error) {
        console.error(error);
      }
    };

    fetchData();
  }, []);
like image 42
DSDmark Avatar answered Feb 07 '26 15:02

DSDmark