object property returns undefined even though it exists JavaScript

Viewed 49

I'm trying to make a clone system of Pokemon, using objects. Using PokeAPI, I get all the pokemon's evolutions, and if the pokemon has more than 1 evolution, (I.E Kirlia), It pushes all the evolution object properties the Pokemon.evolutions, which is an array of these evolution objects. When I try to compile the code It crashes saying: TypeError: Cannot read properties of undefined (reading 'species'), so I think that it means because I typed the object wrong, but That's not it, If I console.log data.evolves_to[i].species.name (the line causing the app to crash), I get the pokemon name, and it's correct! and then it crashes on the same line! It gets logged in the console and then crash. What's going on? Here's the code for context:

 async getRandomPokemon() {
    const rawData: PokemonData[] | PokemonSpecies[] = [];
    const id = utils.rng({ min: 1, max: 898 });
    rawData[0] = await api.getPokemonById(id);
    rawData[1] = await api.getPokemonSpeciesById(id);
    const pokemon: Pokemon = {
      name: rawData[0].name,
      level: utils.rng({ min: 1, max: 10 }),
      gender: utils.pick({ array: ["male", "female"] }),
      exp: 1,
      stats: {
        hp: rawData[0].stats[0].base_stat,
        atk: rawData[0].stats[1].base_stat,
        def: rawData[0].stats[2].base_stat,
        spa: rawData[0].stats[3].base_stat,
        spd: rawData[0].stats[4].base_stat,
        spe: rawData[0].stats[5].base_stat,
        IVs: {
          hp: utils.rng({ min: 0, max: 31 }),
          atk: utils.rng({ min: 0, max: 31 }),
          def: utils.rng({ min: 0, max: 31 }),
          spa: utils.rng({ min: 0, max: 31 }),
          spd: utils.rng({ min: 0, max: 31 }),
          spe: utils.rng({ min: 0, max: 31 }),
        },
        EVs: {
          hp: utils.rng({ min: 0, max: 252 }),
          atk: utils.rng({ min: 0, max: 252 }),
          def: utils.rng({ min: 0, max: 252 }),
          spa: utils.rng({ min: 0, max: 252 }),
          spd: utils.rng({ min: 0, max: 252 }),
          spe: utils.rng({ min: 0, max: 252 }),
        },
      },
      moves: [],
      evolutions: [],
      aesthetics: {
        sprite: rawData[0].sprites.front_default,
        color: rawData[1].color.name,
      },
      rarity: {
        isLegendary: rawData[1].is_legendary,
        isMythical: rawData[1].is_mythical,
        catchRate: rawData[1].capture_rate,
      },
    };
    const json = await axios(rawData[1].evolution_chain.url);
    let data = json.data.chain;
    for (let i = 0; i < data.evolves_to.length; i++) {
      const one: boolean = data.evolves_to[i].evolves_to.length === 0;
      pokemon.evolutions.push({
        first: data.species.name,
        second: {
          name: data.evolves_to[i].species.name,
          mode: {
            name: data.evolves_to[i].evolution_details[0].trigger.name,
            gender: data.evolves_to[i].evolution_details[0].gender,
            level: data.evolves_to[i].evolution_details[0].min_level,
            item: data.evolves_to[i].evolution_details[0].item
              ? data.evolves_to[i].evolution_details[0].item.name
              : null,
            happiness: data.evolves_to[i].evolution_details[0].min_happiness,
            move: data.evolves_to[i].evolution_details[0].known_move,
          },
        },
        third: one
          ? null
          : {
              name: one ? null : data.evolves_to[i].evolves_to[0].species.name,
              mode: {
                name: data.evolves_to[i].evolves_to[0].evolution_details[0]
                  .trigger.name,
                gender:
                  data.evolves_to[i].evolves_to[0].evolution_details[0].gender,
                level:
                  data.evolves_to[i].evolves_to[0].evolution_details[0]
                    .min_level,
                item: data.evolves_to[i].evolves_to[0].evolution_details[0].item
                  ? data.evolves_to[i].evolves_to[0].evolution_details[0].item
                      .name
                  : null,
                happiness:
                  data.evolves_to[i].evolves_to[0].evolution_details[0]
                    .min_happiness,
                move: data.evolves_to[i].evolves_to[0].evolution_details[0]
                  .known_move,
              },
            },
      });
      if (data.evolves_to[0].evolves_to.length > 1) {
        for (let i = 0; i < data.evolves_to[0].evolves_to.length; i++) {
          console.log(data.evolves_to[i].species.name);
          pokemon.evolutions.push({
            first: data.species.name,
            second: {
              name: data.evolves_to[i].species.name,
              mode: {
                name: data.evolves_to[i].evolution_details[0].trigger.name,
                gender: data.evolves_to[i].evolution_details[0].gender,
                level: data.evolves_to[i].evolution_details[0].min_level,
                item: data.evolves_to[i].evolution_details[0].item
                  ? data.evolves_to[i].evolution_details[0].item.name
                  : null,
                happiness:
                  data.evolves_to[i].evolution_details[0].min_happiness,
                move: data.evolves_to[i].evolution_details[0].known_move,
              },
            },
            third: one
              ? null
              : {
                  name: one
                    ? null
                    : data.evolves_to[i].evolves_to[0].species.name,
                  mode: {
                    name: data.evolves_to[i].evolves_to[0].evolution_details[0]
                      .trigger.name,
                    gender:
                      data.evolves_to[i].evolves_to[0].evolution_details[0]
                        .gender,
                    level:
                      data.evolves_to[i].evolves_to[0].evolution_details[0]
                        .min_level,
                    item: data.evolves_to[i].evolves_to[0].evolution_details[0]
                      .item
                      ? data.evolves_to[i].evolves_to[0].evolution_details[0]
                          .item.name
                      : null,
                    happiness:
                      data.evolves_to[i].evolves_to[0].evolution_details[0]
                        .min_happiness,
                    move: data.evolves_to[i].evolves_to[0].evolution_details[0]
                      .known_move,
                  },
                },
          });
        }
      }
    }
    return pokemon;
  },

The line that crashes the app is console.log(data.evolves_to[i].species.name); (106, almost at the bottom). The strange thing is that data.evolves_to[i].species.name is already in use when getting the first evolution, but crashes when trying to get the alternate evolutions.

1 Answers

The for loop right above your console.log is causing the problem

for (let i = 0; i < data.evolves_to[0].evolves_to.length; i++)

You have "data.evolves_to[0].evolves_to.length" when I think you only need "data.evolves_to.length".

This would happen if you have fewer objects in "data.evolves_to" than in "data.evolves_to[0].evolves_to", whatever that happens to be.

You can try to find errors like by stepping through the program using the browsers development console.

It's obviously a copy & paste error, now that we know what to look for.

Related