2

I am new to javascript and Reactjs and I am trying to fetch data from an api and then set an variable in my state to that data. When I console.log the response after I convert it to JSON, it works fine. However, after I set the data in this.state to the response and try to console.log(this.state.data) in my state, it shows an empty object in the console.

import React, {Component} from 'react';
import './App.css';
import Plot from 'react-plotly.js';

class App extends Component{
  constructor(){
    super();
    this.state = {data: {}}
  }

  componentDidMount(){
    fetch("https://alpha-vantage.p.rapidapi.com/query?symbol=TSLA&function=GLOBAL_QUOTE", {
        "method": "GET",
        "headers": {
          "x-rapidapi-host": "alpha-vantage.p.rapidapi.com",
          "x-rapidapi-key": "230d86db60msheb2e40d44790598p1915e2jsn5074c9944675"
        }
    })
      .then(response => response.json())
      .then(response => {
        console.log(response)
        this.setState({data: response})
      })
    
    console.log(this.state.data)
  }

  render(){
    return(
      <h1></h1>
    )
  }
}

export default App;
chibiw3n
  • 357
  • 2
  • 15

3 Answers3

2

You are console logging after an asynchronous callback. Meaning the console.log(this.state.data) is called, when the data hasn't been changed, yet.

Nils Schwebel
  • 641
  • 4
  • 14
2

Your console.log(this.state.data) gets called immediately in the callstack after the fetch function gets called ,so it gets the current value of data which is empty js object (which you initialized in your constructor)

 componentDidMount(){
    fetch("https://alpha-vantage.p.rapidapi.com/query?symbol=TSLA&function=GLOBAL_QUOTE", {
        "method": "GET",
        "headers": {
          "x-rapidapi-host": "alpha-vantage.p.rapidapi.com",
          "x-rapidapi-key": "230d86db60msheb2e40d44790598p1915e2jsn5074c9944675"
        }
    })
      .then(response => response.json())
      .then(response => {
        console.log(response)
        this.setState({data: response});

      })
    
    console.log(this.state.data) // this gets called immediately after fetch and so it contains the empty data object
  }

Instead try moving this console.log inside the fetch

 componentDidMount(){
        fetch("https://alpha-vantage.p.rapidapi.com/query?symbol=TSLA&function=GLOBAL_QUOTE", {
            "method": "GET",
            "headers": {
              "x-rapidapi-host": "alpha-vantage.p.rapidapi.com",
              "x-rapidapi-key": "230d86db60msheb2e40d44790598p1915e2jsn5074c9944675"
            }
        })
          .then(response => response.json())
          .then(response => {
            console.log(response)
            this.setState({data: response});
          console.log(this.state.data). // now it will print the data which you set in the state
   
          })
        
       
      }
Shubham Dixit
  • 9,242
  • 4
  • 27
  • 46
2

First of all, you are changing state inside asynchronous call, and line

this.setState({data: response});

executes unpredictably after the line

console.log(this.state.data),

Secondly, as said in React documentation,

State Updates May Be Asynchronous. React may batch multiple setState() calls into a single update for performance.

Therefore, by calling setState you are scheduling state update, not updating it immediately.

Skeptik
  • 49
  • 1
  • 4