Can't get the data into state

Can't get the data into state
0.0 0

#1

I have just started the react projects. In the leaderboard project I can retrieve the data from the API but cannot seem to get it into the state so that I can use it. I get the following error using the code below - any help would be great.

error message
Uncaught (in promise) TypeError: Cannot read property 'setState' 
of undefined at pen.js:55:13
class LeaderTable extends React.Component{
  
  constructor(){
    super();
    this.state = {
      fccdata: []
    };
    this.setState = this.setState.bind(this);
  }
  
  render(){
    fetch('https://fcctop100.herokuapp.com/api/fccusers/top/recent')  
      .then(
        function(response) {
          if (response.status !== 200) {  
            console.log('Looks like there was a problem. Status Code: ' +  
              response.status);  
            return;  
          }
          response.json().then(function(data) {
            this.setState({
              fccdata: data
            });
          });  
        }  
      )
      .catch(function(err) {
        console.log('Fetch Error :-S', err);  
      });
    
    return(
      <h1>data {this.state.fccdata}</h1>
    );
  }
}

ReactDOM.render(
  <LeaderTable />,
  document.getElementById('root')
);

#2

You can’t update state in render().
Also you don’t have to bind it in constructor.


#3

As jenovs mentioned, there are a couple structural issues with your code. I’m curious what example or lesson you’re following that’s demonstrating these methods. It would also be helpful if the code was in CodePen for debugging.

this.setState = this.setState.bind(this); is unnecessary since setState is a built-in method and setState() can’t be done inside render().

I used setState inside methods like componentDidMount() (which is also where I performed the API calls) and in events that i defined like onClick.

A short example to contrast to what you have (for structure guidance, dont know if this exact code works):

class LeaderTable extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      fccdata: []
    };
    this.someAction = this.someAction.bind(this);
  }

  componentDidMount() {
    var parent = this;
    fetch('https://fcctop100.herokuapp.com/api/fccusers/top/recent')  
      .then(
        function(response) {
          if (response.status !== 200) {  
            console.log('Looks like there was a problem. Status Code: ' +  
              response.status);  
            return;  
          }
          response.json().then(function(data) {
            parent.setState({
              fccdata: data
            });
          });  
        }  
      )
      .catch(function(err) {
        console.log('Fetch Error :-S', err);  
      });
  }

  someAction(event) {
    this.setState({sort: 'recent'});
  }

  render(){
    return(
      <h1 onClick={this.someAction}>data {this.state.fccdata}</h1>
    );
  }
}
ReactDOM.render(
  <LeaderTable />,
  document.getElementById('root')
);

#4

Thanks guys appreciate the help. I was trying to implement the first option suggested in this article were I have a single component which uses fetch() (avoiding jquery) to get the data and store it in the state. As suggested I put your suggested code into codepen but get different errors.


#5

You are trying to output an array in your render() method (<h1>data {this.state.fccdata}</h1>). You can’t do it.
You should create a function to parse this.state.fccdata


#6

Thanks for the assistance. I moved the code to the constructor - I think my problem was a lack of understanding of the this keyword. when used inside the .then block - this - is undefined instead of referencing the Component object. I guess the constructor is the best place to initialise the code. Thanks again.

class LeaderTable extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      fccdata: []
    };
    const leadertableobj = this;
    // console.log(this);
    fetch('https://fcctop100.herokuapp.com/api/fccusers/top/recent')  
      .then(
        function(response) {
          if (response.status !== 200) {
            console.log('Looks like there was a problem. Status Code: ' +  
              response.status);  
            return;  
          }
          response.json().then(function(data) {
            // console.log(this);
            leadertableobj.setState({
              fccdata: data
            });
          });  
        }  
      )
      .catch(function(err) {
        console.log('Fetch Error :-S', err);  
      });
  }

  render(){
    console.log(this.state.fccdata);
    return(
      <h1>data</h1>
    );
  }
}

ReactDOM.render(
  <LeaderTable />,
  document.getElementById('root')
);

#7

Not really.

Read about The Component Lifecycle

Pay attention to componentDidMount() part.