-1

I'm currently trying to learn ReactJS and running into some issues with state and useEffect - If I take the following React code:

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

const interval = {
  limit: 25
}

const App = (props) => {
  const { pokedex, } = props
  const [pokemonList, setPokemonList] = useState([])

  useEffect(() => {
    const getPokemonListData = async () => {
      let pokemon = await pokedex.getPokemonsList(interval)
      setPokemonList(pokemon.results)
    }

    getPokemonListData()

  }, [])

  return (
    <div className="App">
      <h1>Pokedecs</h1>

        <div className="container">
          {
            pokemonList?.map(poke => {
              return <PokemonCard key={poke.name} pokedex={pokedex} pokemonName={poke.name} />
            })
          }
        </div>

    </div>
  );
}

export default App;
import { useEffect, useState } from "react"
import PokemonTypePill from "./PokemonTypePill"
import '../App.css';

const PokemonCard = (props) => {
    let styles = {
        card: {
            backgroundColor: "#fff",
            height: "200px",
            width: "150px",
            boxShadow: '1px 2px 5px #000000',
            margin: "15px",
            textAlign: "center",
            borderRadius: "12px",
            fontWeight: "bold",
            transition: "transform .2s"
        }
    }

    const {pokemonName, pokedex, } = props
    const [pokemonData, setPokemonData] = useState({})

    const getPokemonData = async () => {
        let pokemon = await pokedex.getPokemonByName(pokemonName)
        setPokemonData(pokemon)
    }

    const pokemonTypes = () => {
        console.log(pokemonData) //this always uses the initial state "{}"
    }

    useEffect(() => {
        getPokemonData()
        pokemonTypes()
    }, [setPokemonData])

    return (
        <div className="card" style={styles.card}>
            <img src={pokemonData.sprites && pokemonData.sprites?.front_default} />
            <p>#{pokemonData.id} {pokemonName.charAt(0).toUpperCase() + pokemonName.slice(1)}</p>
            <div style={{width: "inherit", display: "flex", alignContent: "center", justifyContent: "center"}}>
                {
                    pokemonData.types?.map((pokemonType) => {
                        return (
                            <PokemonTypePill key={pokemonType.type.name} typeName={pokemonType.type.name} />
                        )
                    })
                }
            </div>
        </div>

    )
}

export default PokemonCard

In the Component "PokemonCard" inside of the pokemonTypes method, on first load, the data is printed to the console with the updated state of "pokemonData". When the page is refreshed, the empty objects are printed to the console, which is the initial state. Why does the data print to the console on the initial load, but on refresh it reverts back to the initial state.

DCWD
  • 11
  • 6
  • 1
    Is this code copy pasted? You've spelt useEffect incorrectly. It also looks like it has lots of weird errors like %% – Mark Barton Mar 16 '23 at 11:27
  • I would expect this to produce an error: `apiData?.results.map` Because `apiData` is not `null` or `undefined`, it's a valid object. But it has no `results` property. So *that property* is `undefined`, and you can't call `.map()` (or anything else) on `undefined`. This will fail before `ComponentOne` is ever even invoked. Is that the "undefined" that you're referring to? It's not really clear from the question. – David Mar 16 '23 at 11:28
  • I've updated the code to fix the typos and %% – DCWD Mar 16 '23 at 11:35
  • @David I've updated the code to fix the map in App.js - The issue is when ComponentOne receives the data from as a prop from App.js. In the doSomethingWithData method in Component one, on first page load, it gets the data and prints it to the console, when you refresh its now undefined or an emptyArray and I can't figure out why – DCWD Mar 16 '23 at 11:37
  • @DCWD: Did you also fix these issues in the actual original code and re-test? Has the problem changed in any way? Correcting one error would *very likely* mean that if something still "doesn't work" then it's an entirely different error. (Even if it's still the same error message, the debugging of it has changed.) – David Mar 16 '23 at 11:37
  • @David yes, on first page load the data is fine and its printed to the console, on refresh the console.log(newArray) prints empty arrays – DCWD Mar 16 '23 at 11:41
  • 1
    @DCWD: The code in this question is too much of a "moving target" and, given the edit history, is very clearly not the actual code you're using. This results in essentially a game of "whack a mole" where we continue to point out problems and you continue to fix typos and say "it still doesn't work", which doesn't help you. Please take some time to provide a runnable [mcve] which demonstrates the problem and indicate specifically what problem you are observing in that example. – David Mar 16 '23 at 11:45
  • @David I've added the actual code, I was on another machine so was trying to use psuedo code, apologies - the above code is more or less identical. – DCWD Mar 16 '23 at 11:55
  • 1
    @DCWD: And what specifically is the observed problem in this new, drastically different code? The code no longer indicates anything being "undefined". The question still asks about "ComponentOne", which isn't in the code shown. The question says *"data only works on the first page load"*... What specific "data"? What specifically "doesn't work" about it? What specific problem are you observing? What specific result were you expecting for that operation? Why? The game of whack-a-mole continues... – David Mar 16 '23 at 12:02
  • @David I have updated the question to be more specific to the code. Do you need any more detail or does that suffice? – DCWD Mar 16 '23 at 12:08
  • @DCWD: This is looking like essentially a duplicate of [this question](https://stackoverflow.com/q/54069253/328193). It's likely that you're also making mistakes and false assumptions in your observations as well. But when you call `pokemonTypes()` your state has not yet been updated, so it's going to show the *current* value of `pokemonData`, which was explicitly set to `{}`. Then it doesn't appear that `pokemonTypes()` ever gets invoked again for that component. – David Mar 16 '23 at 12:12

1 Answers1

0

When the page loads the first time then you will get the data from the API but when you refresh the page then you are not calling the API again that's why you are getting undefined. You can follow one of the methods to solve this issue:-

  1. You can create a function for getting the data from API & can pass as prop to that component & in that component you can simply call that function in useEffect.

  2. You can call the API directly in useEffect & set the setPokemonList with this API data.

Hope it will solve your issue.

Ritik
  • 51
  • 7