Search code examples
reactjsaxiosuse-effectuse-state

How do you access data from axios?


Here's what I have

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

const BASE_URL = 'https://api.pokemontcg.io/v1/cards'

const App = () => {

const [image,setImage] = useState([])

useEffect(() => {
axios.get(`${BASE_URL}`)
.then(function (response) {
  setImage(response.data)
})
.catch(function (error) {
  console.log(error);
})
},[])

This works...

console.log(image) // displays an ARRAY OF OBJECTS

This is expected to work, but doesn't...

console.log(image[0].name)

The reason the latter console.log is expected to work is because image is definitely an array of objects. I know that for a fact. So, [0] would pick out the first array, you would think And name is the name of the key value pair. So, the broken piece of this console.log(image[0].name) should pick out the value of the name of the first array in the image array of objects.

I would appreciate your help trying to figure out why this hasn't been working for the last 8 hours of searching the globe for an answer that apparently Google doesn't have.


Solution

  • const [image,setImage] = useState([]) initializes the state as an empty array. And the useEffect hook will run after the component has been mounted for the first time. Which means the first time the component renders with state value of image still being an empty array([]), so when you try to access image[0].name because image[0] in undefined it produces the error.

    Because the array image is populated by the asynchronous API call after the component has mounted for the first time, if you want to log image[0].name the simplest way is to check for the length of the array then log the name of the first element. The same check has to be done if you want to pass image[0].name as a prop.

    For example,

    if (image.length) {
      console.log(image[0].name) // expected result will be logged
    }
    
    // if you want to pass the value of image[0].name as a prop
    return (
      <div>
       {
        image.length && <SomeComponent imgName={image[0].name}/>
       }
      </div>
    )