skip to Main Content

This is my ReactJS code

export default class HomeNew extends Component {

  state = {
    anime: [], // Initialize with an empty array
  };
  

  componentDidMount(){

    axios.get(URL_POPULAR).then((response) =>{
      const animeData = response.data.results.slice(0,3);
      //console.log(animeData)
      let slider_data = []
      for(let i = 0 ; i<animeData.length; i++){

        //console.log(animeData[i])

        axios.get(URL_INFO+`?id=${animeData[i].animeId}`).then((res) =>{
          //console.log(res.data)
          slider_data[i] = {
            "animeName" : res.data.title,
            "animeImage": res.data.image,
            "animeDes": res.data.description,
            "animeId" : animeData[i].animeId

          }
        } )
        
      }
      //console.log(slider_data)
      this.setState({ anime: slider_data })
      
    })

  }

  render() {

    const {anime} = this.state
    console.log(anime) //this gives array of 3 objects that i need
console.log(anime[0]) //this gives undefined


    return (
      <>
      i want to access those data here
but anime[0] gives undefined
      </>
    )
  }
}

When i print on console , anime state variable, it does gives 3 objects, but why when i do anime[0] it gives undefined
How to solve this, i am struggling for 3 hrs with this issue

Please HELP

2

Answers


  1. You are having an async/await problem. Try this instead. Additionally, mark componentDidMount with async. When you update the state, the view is rerendered, so you must be able to view the slider_data.

    const response = await axios.get(URL_INFO+`?id=${animeData[i].animeId}`)
    slider_data[i] = {
     "animeName" : response.data.title,
     "animeImage": response.data.image,
     "animeDes": response .data.description,
     "animeId" : animeData[i].animeId
    }
           
    

    Full code:

        async componentDidMount(){
        axios.get(URL_POPULAR).then((response) =>{
          const animeData = response.data.results.slice(0,3);
          //console.log(animeData)
          let slider_data = []
          for(let i = 0 ; i<animeData.length; i++){
    
            //console.log(animeData[i])
    
            const response = await axios.get(URL_INFO+`?id=${animeData[i].animeId}`)
           slider_data[i] = {
             "animeName" : response.data.title,
             "animeImage": response.data.image,
             "animeDes": response .data.description,
             "animeId" : animeData[i].animeId
            }
            
          }
          //console.log(slider_data)
          this.setState({ anime: slider_data })
          
        })
    
      }
    
    Login or Signup to reply.
  2. Issue

    You are fetching data asynchronously, and mutating the slider_data reference. Since the for-loop is completely synchronous the this.setState({ anime: slider_data }) runs before the GET requests resolve and the slider_data reference is saved into state. When the GET requests resolve the slider_data array is mutated. You are seeing this mutation exposed in the console logs in the render function when you examine them in the console.

    Solution

    Rework the axios calls to wait until all the GET requests resolve then enqueue a state update to anime. Add a check in the render method to ensure state.anime is a populated array prior to access elements in it.

    export default class HomeNew extends Component {
      state = {
        anime: [],
      };
    
      componentDidMount() {
        axios.get(URL_POPULAR)
          .then((response) => {
            const animeData = response.data.results.slice(0, 3);
    
            // Create array of requests
            const animeReqs = animeData.map(
              anime => axios.get(URL_INFO+`?id=${anime.animeId}`)
                .then(result => ({
                  anime,
                  result,
                }))
            );
    
            // Return array of requests
            return Promise.all(animeReqs);
          })
          .then(results => {
            // Map resolved values to new anime state
            const slider_data = results.map(({ anime, result }) => ({
              "animeName": result.data.title,
              "animeImage": result.data.image,
              "animeDes": result.data.description,
              "animeId": anime.animeId
            }));
    
            // Enqueue anime state update
            this.setState({ anime: slider_data });
          });
      }
    
      render() {
        const { anime } = this.state;
        console.log(anime); // this gives array of 3 objects that i need
    
        if (anime.length) {
          console.log(anime[0]); // <-- can log populated array element
    
          return (
            <>
              Access anime[0..3] data here
            </>
          );
        } else {
          // data not loaded yet
        }
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search