Home > front end >  Array is shuffling in React JS
Array is shuffling in React JS

Time:03-28

I'm trying to display an array with 151 pokemons sorted by their pokedex positions (ex: 1 - bulbasaur, 2- ivysaur...), but every time I reload the page it brings me a different array, with the positions shuffled.

App.js:

import './App.css';
import { useEffect, useState } from 'react';
import Pokemon from './components/Pokemon';

const App = () => {
  const [pokemonData, setPokemonData] = useState([]);

  const fetchPokemons = () => {
    for (let index = 1; index < 152; index  = 1) {
      new Array(151).fill(
        fetch(`https://pokeapi.co/api/v2/pokemon/${index}`)
          .then((data) => data.json())
          .then((result) =>
            setPokemonData((prevState) => [...prevState, result])
          )
      );
    }
  };

  useEffect(() => {
    fetchPokemons();
  }, []);

  return (
    <>
      {pokemonData && <Pokemon data={pokemonData} />}
    </>
  );
};

export default App;

Pokemon.js:

const Pokemon = ({ data }) => {
  return (
    <section>
      {data.map((pokemon) => (
        <div key={pokemon.name}>
          <img src={pokemon.sprites.front_default} alt={pokemon.name} />
          <span>{pokemon.name}</span>
          <span>
            {pokemon.types.length >= 2
              ? `${pokemon.types[0].type.name}  ${pokemon.types[1].type.name}`
              : pokemon.types[0].type.name}
          </span>
        </div>
      ))}
    </section>
  );
};

export default Pokemon;

CodePudding user response:

If you want to guarantee the order, you'll need something like

  const fetchPokemons = async () => {
    const promises = [];
    for (let index = 1; index < 152; index  = 1) {
      promises.push(fetch(`https://pokeapi.co/api/v2/pokemon/${index}`).then((data) => data.json()));
    }
    const results = await Promise.all(promises);
    setPokemonData(results);
  };

This will take a while as it loads all of the pokémon before showing any of them - if you don't want that, then there really are two options: rework things to do each request sequentially, or alternately switch to an array where some of the slots may be null while things are still being loaded (which will require changing your rendering code some too).

CodePudding user response:

You are making 153 calls to api, which is not great I would highly recommend that you change into single api call to get all pokemons, to achieve this you can do it like this:

const [pokemonData, setPokemonData] = useState<any>([]);

  const fetchPokemons = async () => {
      const data = await fetch(`https://pokeapi.co/api/v2/pokemon?offset=0&limit=153"`);
      const pokemons = await data.json();
      setPokemonData(pokemons.results);
  };

  useEffect(() => {
    (async () => {
      await fetchPokemons();
    })();
  }, []);

Also this will guarantee that you get data always in the same way. You will not face any race conditions and you won't any unnecessary api calls.

  • Related