0

So the API I'm working with doesn't have one source to get all the Pokemon, but it has links to each with their id as the parameter. I'm using a for loop to get all the requests. I did this synchronously using async await, but it was really slow.

The code isn't working. It's getting the requests, but it's not properly updating the map. It only logs the current map before it gets the requests.

import React from 'react'
import axios from 'axios'

//Defines what a Pokemon has
interface Pokemon {
    name: string,
    id: number,
    sprite: string
}

const PokemonList2: React.FC<{}> = (props) => {
    //The state is a Map of pokemon. Key is the Pokemon's name, value is a Pokemon object
    const [pokemonMap, setPokemonMap] = React.useState<Map<string, Pokemon>>(new Map<string, Pokemon>())

    //Handles API request
    React.useEffect(() => {
        //Sets the temporary map equal to the state's map
        let tempPokemonMap: Map<string, Pokemon> = pokemonMap

        //loops through pokemon
        for (let i = 1; i <= 50; i++){
            //says it's loading
            console.log('loading...')

            //gets the request
            axios.get('https://pokeapi.co/api/v2/pokemon/' + i)
                .then(res => {
                    //adds the new pokemon to the map
                    tempPokemonMap.set(res.data.name, {
                        name: res.data.name,
                        id: res.data.id,
                        sprite: res.data.sprites.front_default
                    })

                    //Sets the state map to the temp map
                    setPokemonMap(tempPokemonMap)

                    //logs that is was added
                    console.log(`Added ${ res.data.id } : ${ res.data.name }`)
                })
        }

    }, [setPokemonMap, pokemonMap])

    //logs the current map
    console.log(pokemonMap)

    //Gets JSX from the map
    let pokemonJSX: JSX.Element[] = []
    pokemonMap.forEach(pok => {
        pokemonJSX.push(
            <div key={ pok.id } style={{ textAlign: "center" }}>
                <p>{ pok.name }</p>
                <img src={ pok.sprite } alt={ pok.name }/>
            </div>
        )
    })

    //Prints the JSX
    return (
        <div className="container">
            { pokemonJSX }
        </div>
    )
}

export default PokemonList2
ZeroSevenTen
  • 1,122
  • 2
  • 9
  • 20
  • Don't do multiple requests in a for loop. Do it like this instead: https://stackoverflow.com/questions/52669596/promise-all-with-axios – d3bgger Apr 21 '20 at 19:44

1 Answers1

0

In this case your issue is that when you assign tempPokemonMap to be pokemonMap, you're not actually copying the value of pokemonMap onto your variable, but merely passing the reference. When you later try to update your state, you're passing the same reference to the object that is already in state, which is why React doesn't detect any changes, and why it doesn't rerender.

Furthermore, I would also suggest that as d3bgger mentioned, that you do all your requests, and then update the state. Both in terms of performance and user experience.

Stephan Olsen
  • 1,623
  • 1
  • 14
  • 29