Home > Mobile >  Duplicated elements after mapping array pulled from API
Duplicated elements after mapping array pulled from API

Time:12-12

I just tried to list all the pokemonsfrom 1 gen using Poke API but after getting the data using axios and mapping array i received duplicated items. Do you have any idea how to fix it? It's my first project with API.

import React from "react";
import Card from "./Card";
import axios from "axios";

export default function Main() {
  const [allPokemons, setAllPokemons] = React.useState([]);

  React.useEffect(() => {
    axios.get("https://pokeapi.co/api/v2/pokemon?limit=151").then((res) => {
      const pokeUrls = res.data.results.map((pokemon) => pokemon.url);

      pokeUrls.map((url) =>
        axios.get(url).then((res) => {
          setAllPokemons((urls) => [...urls, res.data]);
        })
      );
    });

    
  }, [0]);

  console.log(allPokemons);

  const pokemonCard = allPokemons.map((pokemon) => (
    <Card
      name={pokemon.name}
      key={pokemon.id}
      id={pokemon.id}
      img={pokemon.sprites.front_default}
      type={pokemon.types[0].type.name}
    />
  ));

  return <div className="main-container">{pokemonCard}</div>;
}

i tried to change:

pokeUrls.map((url) =>
        axios.get(url).then((res) => {
          setAllPokemons((urls) => [...urls, res.data]);
        })
      );
    });

to:

pokeUrls.map((url) =>
        axios.get(url).then((res) => {
          setAllPokemons(res.data);
        })
      );
    });

but unfortunately in this case i received the error: "Uncaught TypeError: allPokemons.map is not a function"

CodePudding user response:

Three issues I see...

  1. Having [0] in your effect hook's dependencies makes no sense. Just use [] to have it run once on mount
  2. The inner requests will resolve in the order of whatever responds fastest. This means the order of results from the first request won't be the order you end up with in state.
  3. Because your effect hook only adds to the state data, you will end up with duplicates if it runs more than once. For example, this happens with <StrictMode>.

Try resolving all the data only once to maintain order and a clean state...

const getAllPokemon = async (limit = 151) => {
  const {
    data: { results },
  } = await axios.get("https://pokeapi.co/api/v2/pokemon", {
    params: { limit },
  });

  return Promise.all(
    results.map(async ({ url }) => (await axios.get(url)).data)
  );
};

and in your component

useEffect(() => {
  getAllPokemon().then(setAllPokemons).catch(console.error);
}, []);

I also suspect you're seeing multiple log entries. This is because your state is updated every time a response is received which will result in multiple renders and thus, multiple console.log(allPokemons). Note that this does not mean you have duplicate data.

I strongly suggest never using console.log() for anything other than simple logging. Just use your data instead of worrying about what it looks like in the console.

  • Related