0

It's my first stackoverflow querstion so be gentle for me 😅

I'am making pokedex app with react query and fetch but I have problem with returning array of my pokemons.

I'm trying to fetch a pokeApi which returns an array of results consisting of objects with another url. Then I try to map trough results array and fetch url for individual pokemon then push it to the arr variable. In the end, I'am returning arr which is not readable.

How to properly push data to arr in map?

What i'am doing wrong? Is there solution?


const fetchData = async (key) => {
    const data = await fetch(`https://pokeapi.co/api/v2/pokemon`)
      .then((res) => res.json())
      .then((data) => {
        return data;
      });
    const arr = [];
    data.results.map((item) => {
      return fetch(item.url)
        .then((res) => res.json())
        .then((data) => {
          arr.push(data);
        });
    });
    return arr;
  };

  const { isLoading, data } = useQuery("pokemons", fetchData, {
    refetchOnWindowFocus: false
  });

  if (isLoading) return <div>loading...</div>;
  console.log(data); // cant read
  return <div>Data loaded</div>;

https://codesandbox.io/s/strange-pond-wz4ws?fontsize=14&hidenavigation=1&theme=dark

2
  • You await the response but you do not await the parsing of json which is also async. In general you should not mix await with .then(). Use one or the other. Also inside of your map() callback you are returning a Promise instead of an actual result as fetch() is async. Commented Oct 8, 2020 at 10:12
  • so how should my code look? Commented Oct 8, 2020 at 11:33

2 Answers 2

1

The issue with your fetchData function, is that it does not wait for any of the subsequent fetches for each item.

To solve this, you have to map each of the results as a Promise, then wait for all these promises to finish by utilizing Promise.all

Your fetchData function might look something like this:

  const fetchData = async (key) => {
    const data = await fetch(`https://pokeapi.co/api/v2/pokemon`)
      .then((res) => res.json())
      .then((data) => {
        return data;
      });

    // Wait for all subsequent fetches to finish
    const arr = await Promise.all(
      data.results.map((item) => fetch(item.url).then((res) => res.json()))
    );

    return arr;
  };
Sign up to request clarification or add additional context in comments.

2 Comments

but how now I push to arr my fetch(item.url) response data?
@Pero You don't need to push it into the array. map() returns an array of promises and Promise.all awaits all of them. The result is already what you want. You should not use map() together with push() at all because map() already creates and fills an array. push() only makes sense with forEach().
0

The solution proposed by @JAM but without any .then(). Error handling is omitted (You can use catch() or a try/except block):

const fetchData = async key => {
    const res = await fetch(`https://pokeapi.co/api/v2/pokemon`);
    const data = res.json();

    // Wait for all subsequent fetches to finish
    return Promise.all(
        data.results.map(async item => {
            const res = await fetch(item.url);
            return res.json();
        }
    );
};

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.