Oskar Nawara
Oskar Nawara

Reputation: 49

Problem with using deeper nested data fetched from API

I encountered a problem when I try to fetch some data from PokeAPI. Here's my code for PokemonCard component.

import React, { useEffect, useState } from "react";
import axios from "axios";

const PokemonCard = ({ pokemonID }) => {
  const [pokemon, setPokemon] = useState({});
  useEffect(() => {
    (async () => {
      const result = await axios.get(
        `http://pokeapi.co/api/v2/pokemon/${pokemonID + 1}`
      );
      setPokemon(result.data);
    })();

    // console.log(pokemon.weight)
  }, [pokemonID]);
  return (
    <div className="pokemon">
      {pokemon.sprites.front_default}
    </div>
  );
};

export default PokemonCard;

Everything works properly when I try to reach data like: pokemon.weight or pokemon.base_experience. But I get errors when I try to use some deeper nested variables.

pokemon.sprites.front_default gives me an error TypeError:

Cannot read property 'front_default' of undefined.

Here's a sample of data from API:

    "name": "bulbasaur",
    "order": 1,
    "species": {
        "name": "bulbasaur",
        "url": "https://pokeapi.co/api/v2/pokemon-species/1/"
    },
    "sprites": {
        "back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/back/1.png",
        "back_female": null,
        "back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/back/shiny/1.png",
        "back_shiny_female": null,
        "front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/1.png",
        "front_female": null,
        "front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/1.png",
        "front_shiny_female": null
    },
    "stats": [        
        {
            "base_stat": 45,
            "effort": 0,
            "stat": {
                "name": "hp",
                "url": "https://pokeapi.co/api/v2/stat/1/"
            }
        }
    ],
    "types": [
        {
            "slot": 2,
            "type": {
                "name": "poison",
                "url": "https://pokeapi.co/api/v2/type/4/"
            }
        },
        {
            "slot": 1,
            "type": {
                "name": "grass",
                "url": "https://pokeapi.co/api/v2/type/12/"
            }
        }
    ],
    "weight": 69

PS. Is it a good practice to make about 150 separate calls to API in every child component? Or should I somehow do it with one call? Thank you.

Upvotes: 0

Views: 1478

Answers (2)

Penny Liu
Penny Liu

Reputation: 17468

Gets much easier in Optional chaining (?.)

pokemon.sprites?.front_default

Upvotes: 0

Deepak
Deepak

Reputation: 870

You were trying to access a key inside an undefined key of pokemon variable. Please check the updated line where you are actually rendering.

{pokemon.sprites ? pokemon.sprites.front_default : ''}

As Pokemon is an empty object before the api fetches the data and updates to the state, so pokemon.sprites is actually undefined.

import React, { useEffect, useState } from "react";
import axios from "axios";

const PokemonCard = ({ pokemonID }) => {
  const [pokemon, setPokemon] = useState({});
  useEffect(() => {
    (async () => {
      const result = await axios.get(
        `http://pokeapi.co/api/v2/pokemon/${pokemonID + 1}`
      );
      setPokemon(result.data);
    })();

    // console.log(pokemon.weight)
  }, [pokemonID]);
  return (
    <div className="pokemon">
      //this should work for you
      {pokemon.sprites ? pokemon.sprites.front_default : ''}
    </div>
  );
};

export default PokemonCard;

Upvotes: 1

Related Questions