1

I made a pokedex website, just to mess around and I try to render 12 pokemon to a page until the user click on the next page then it will render the next 12 base on the pokeapi: "https://pokeapi.co/api/v2/pokemon?offset=0&limit=12"

  function getAllPokemon(url) {
    fetch(url)
      .then((res) => res.json())
      .then((data) => {

        let allPromise = Promise.all(
          data.results.map((e) => {
            return new Promise((resolve, reject) => {
              resolve(e);
            });
          })
        );
        allPromise.then((e) => {
          e.map((res) => {
            fetch(res.url)
              .then((e) => e.json())
              .then((e) => {
                setListPokemon((listPokemon) => [
                  ...listPokemon,
                  {
                    id: e.id,
                    name: res.name,
                    url: res.url,
                    image_url:
                      e.sprites.other["official-artwork"].front_default,
                  },
                ]);
              });
          });
        });
      });
    setLoading(false);
  }

Then I would use map to render all the data to screen.

{listPokemon.map((p) => (
              <Grid>
                  <Card>
                    <CardMedia
                      component="img"
                      image={p.image_url}
                      alt={p.name}
                    />
                    <CardContent>
                      {p.id}.{setCap(p.name)}
                    </CardContent>
                  </Card>
              </Grid>
            ))}

The problem I have is sometimes map would render the element in random order, most of the time it would still be in ascending order.

From what I notice is that when I try running the app on my phone (which is slower than my PC) this happens more often.

Is this happen because of lag?

Is there a way to make sure that I render the element in the order of which is added?

Tuan Le
  • 37
  • 5

1 Answers1

3

Notice that you are making asynchronous requests inside a for loop. You should make an array of promises and use Promise.all() in such a case. The result will be in a specific order, as explained here, so you will be able to update your state only once with sorted collection of data and then render your list.

wjatek
  • 922
  • 7
  • 22
  • Also you shouldn't place `setLoading(false)` there, it should be done after the last request has finished and the state has been updated. – wjatek Oct 27 '21 at 23:50
  • so do I use promise.all inside the fetch or use promise.all on the fetch? I am not too experience with promises. – Tuan Le Oct 28 '21 at 00:50
  • So i would suggest you to read some [articles](https://dmitripavlutin.com/promise-all/) and [documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all). Basically you need to make an array of promises returned by `fetch` (you can use [map](https://developer.mozilla.org/pl/docs/Web/JavaScript/Reference/Global_Objects/Array/map) function on the `data.results` to generate one), then pass it to the `Promise.all()` function and finally extract your results in a '.then()`, but this time it will be an array of results of successive requests. – wjatek Oct 28 '21 at 20:36
  • So I updated my code (look above) and idk if I am doing it right, but it still doesn't work. – Tuan Le Oct 28 '21 at 22:03
  • Please do not change the code in your question, because the question will make no sense. You made it wrong, as I said you must take the `data.results` array, use `.map()` to generate array of *promises* returned by `fetch()` (not execute `.then()` methods on them!) and then pass it to the `Promise.all()` function. It will return a whole new `Promise` which you need to handle using `.then()`. Read it carefully and look ad the examples in the documentation and the article I linked above. It is quite hard topic, you need to take your time. – wjatek Oct 28 '21 at 22:56
  • Also I forgot to mention that you will need to use `Promise.all()` again to extract data from the responses, because they are also Promises. – wjatek Oct 28 '21 at 23:01
  • [This](https://stackoverflow.com/questions/31710768/how-can-i-fetch-an-array-of-urls-with-promise-all) will help. – wjatek Oct 28 '21 at 23:03