4

I'm working in React and trying to fill a ImageGrid with data from a API. There is no problem with getting the data but somehow I cant set my state with the responseData

I can show the data while I get the response from the API but I can't set my state...

componentWillMount()
{
  this.state = {
    content: ''
  };

   this.loadContent();
}

loadContent()
{
  ApiService.getTweets(topic,numberOfElements,offset).then((responseData) => {
    console.log("Data is here",responseData); //<---------- HERE
    this.setState({
      content: responseData
    });
  })
  console.log("Data is not here",this.state.content); //<---------- HERE
}

Here I get the data:

class ApiService {    

  static getTweets() {      

    return fetch("https://MyURL", {
            method: 'get'
          })
          .then((resp) => resp.json())
          .then(function(data) {

            return data;
          }).catch(function(error) {
            console.log(error);// Error :(
          });
    }
  }
export default ApiService;
Samy
  • 1,013
  • 3
  • 15
  • 25
  • 4
    Two reasons (at least): setState won't set the state immediately, and you're trying to access it before it's been called-you set it in an async callback. – Dave Newton Jun 21 '17 at 13:26
  • Possible duplicate of [Change state on click react js](https://stackoverflow.com/questions/41278385/change-state-on-click-react-js) – Shubham Khatri Jun 21 '17 at 15:03
  • React docs suggest to set the state in the constructor when using ES6 classes. But that should cause this problem. – Priyanshu Chauhan Jun 21 '17 at 18:08

3 Answers3

1

You have async issue: both fetch and setState are async.

loadContent() {
  ApiService.getTweets(topic,numberOfElements,offset).then((responseData) => {
    console.log("Data is here",responseData); //<---------- HERE
    this.setState({
      content: responseData
    }, () => {
       // only now the state was updated
       console.log("Data is here", this.state.content); 
    });

    // even the nest line runs to early
    console.log("Data is not here",this.state.content); 

  })
  // the next line runs to early
  console.log("Data is not here",this.state.content);
}
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98
0

You want to use the set state callback as state is not set instantly.

loadContent() {
  ApiService.getTweets(topic,numberOfElements,offset).then((responseData) => {
    console.log("Data is here",responseData); //<---------- HERE
    this.setState({
      content: responseData
    }, () => {
      console.log("Data is here",this.state.content); //<---------- HERE
    );
  })
}
danday74
  • 52,471
  • 49
  • 232
  • 283
0

You need to implement componentDidUpdate. Don't rely on the promises to know when your component has updated. React's life-cycle will worry about that after the system has updated. See below.

From that point you can easily do something like

componentDidUpdate(prevProps, prevState) {
  if(prevState.content !== this.state.content) {
    console.log('I have new content!', this.state.content);
  }
}

Also, you can ignore that if statement if you only have one setState() call in your component. So the short version is as follows:

componentDidUpdate(prevProps, prevState) {
  console.log('I have new content!', this.state.content);
}
lkg
  • 876
  • 4
  • 10