2 intertdependant gets with axios

Hello everyone, i am working on a small project to learn React, trying to display pokemon sprites and a few infos taken from the famous PokeApi.

My component Pokemon (see below) is not acting as I would like. i tried creating 2 gets. The first one getting the name of every pokemon and the second using said name previously obtained to get an index (stored in another part of the API) allowing me to sort them by number (I cant do it with a simple index, since the numbers dont follow).

Long story short, my first get seems to be working, as I can check it in my browsers console, but the ${data.name} is treated as undefined. Note that when I manually input the name of a pokemon instead of $data.name it works. Of course since you have only the “Pokemon” component it can seem hard to figure out but trust me, it is the only one with an issue, and i’m pretty sure it is an obvious error.Below, the error displayed in the browser’s console.

GET https://pokeapi.co/api/v2/pokemon/undefined 404
performWorkUntilDeadline @ scheduler.development.js:157
createError.js:16 Uncaught (in promise) Error: Request failed with status code 404
at createError (createError.js:16:1)
at settle (settle.js:17:1)
at XMLHttpRequest.onloadend (xhr.js:66:1)

import axios from "axios";
import React, { useEffect, useState } from "react";
import Cards from "./Cards";
let url = "https://pokeapi.co/api/v2/pokemon/?limit=1126";
const Pokemons = () => {
  const [data, setData] = useState([]);
  const [dataSprite, setDataSprite] = useState([]);
  useEffect(() => {
    const fetchdata = async () => {
      const pokeName = await axios(
        "https://pokeapi.co/api/v2/pokemon/?limit=1126"
      ).then((pokeName) => setData(pokeName.data.results));
      const pokeSprite = await axios(

        `https://pokeapi.co/api/v2/pokemon/${data.name}`
      ).then((pokeSprite) => setDataSprite(pokeSprite));
    };
    fetchdata();
  }, []);
  return (
    <div className="pokemon-name">
      <ul>
        {data.map((pokemon, index) => (

          <Cards key={index} pokemon={pokemon} />

        ))}
        {[dataSprite].map((sprite, index) => (
          <li key={index}>{sprite.id}</li>
        ))}
        )
      </ul>
    </div>
  );
};
export default Pokemons;

"

Hi,
you pass the data from the state into the query. I don’t see any usage of the state setter ‘setData’, so I cannot judge if ‘data’ has valid data.
But I see that you initialize it as an array. So you cannot access anything from data with dot notation as that only works for objects. So ‘data.name’ will be undefined.

Hi Mirja, it could be the source of my problem since I already had to encase “dataSprite” in to be able to perform a map on it, even though i dont fully understand why (in my “return”).
But setData is used right after my first fetch and the “pokename.data.results” I pass in is an array of objects

State: [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…

So I tried to use ${data[0].name} in my second fetch but it doesnt change anything.

Oh, ok. Did you log data[0] after the first fetch?
I never worked with axious yet but fetch(). But I don’t think there is much of a difference and you need to convert the stream from the API to a json response by applying .json() to it and then set the result to your state in a 2nd then().

.then((response) => response.json())
.then((pokeSprite) => setDataSprite(pokeSprite));

I recommend logging what you get as a response then. It will be an object, so initializing data as an array and directly setting the state after the fetch without processing the data will probably not lead to the expected result.

Well from what I learned one of the perks of axios is you dont need to convert de response to Json. And it works for my first fectch since I am able to log the names on my browser. Troubles only began when I added the second fetch.

Ok, then there is a difference between the methods.
Still the question: What is logged to the console if you console.log(data[0])?

Hmmm no, actually, logging either data or data[0] tells me that data is undefined. So I guess even my first fetch is trouble.

Yes, that gets me back to my previous point:

Unless you put your console.log() at the wrong place.
I would do it like this:

useEffect(() => {
 console.log(data)
},[data])

and after that ( if data is undefined ):

useEffect(() => {
    const fetchdata = async () => {
      const pokeName = await axios(
        "https://pokeapi.co/api/v2/pokemon/?limit=1126"
      ).then( pokeName => console.log(pokeName));

Yeah no sorry I must have messed something up with logging data, because it definitely has a value. See if I add

{pokemon.name}

right after my .map in results, it works and logs the names on my browser. So data has a value and I can extract the name from it.
return (
    <div className="pokemon-name">
      <ul>
        {data.map((pokemon, index) => (
          <div>
            <Cards key={index} pokemon={pokemon} />
            <p>{pokemon.name}</p>
          </div>
        ))}
        {[dataSprite].map((sprite, index) => (
          <li key={index}>{sprite}</li>
        ))}
        )
      </ul>
    </div>
  );

Ok, then 2 things:

This still doesn’t work, because data.name doesn’t exist. The format for the first would be data[0].name.

If https://pokeapi.co/api/v2/pokemon/${data[0].name} does not return anything, it might be because useEffect is not synchronous. Your second fetch could still get an empty array from data.
Make a second useEffect like:

useEffect(()=>{
if(data.length > 0) {
const pokeSprite = await axios(
        `https://pokeapi.co/api/v2/pokemon/${data.name}`
      ).then((pokeSprite) => setDataSprite(pokeSprite));
}
},[data])

Hmm, this is getting even more confusing, and I cant really tell if I can use 2 usEffect one after the other or put the 2nd into the first one. I guess Ill do 3/4hours of react courses on here and a bunch of tutos hoping to find a similar case.

Thanks for trying and I’ll keep you updated soon on the result.

1 Like

Alrigth, my issue was due to 2 things, you were right, I needed to divide and put each fetch into its own useEffect. But I also failed because of the type of data I was trying to get, I mixed objects and arrays and obviously performing a .map on an object or trying to reach .name in an array wasn’t a good idea.

Thanks for your help, the Codacademy React courses didnt really help since (for the first 50% at least) they dont talk about hooks. But using typeof and console logs did help.

1 Like

They introduce function components in the 2nd half of the React course. That includes a lesson about the useEffect hook. But the useEffect hook is rather complex, so I also needed additional material on this.
console.log() is always helpful, of course.