deek
deek

Reputation: 1095

Reactjs: setState always fails and returns undefined in componentDidMount

Having strange errors using setState(), I always get nothing set to state:

Error code:

TypeError: Cannot read property 'setState' of undefined(…)

class HelloWorld extends React.Component {
constructor() {
    super();
    this.state = {listings:[]};
};

componentDidMount (){
    fetch('./javascripts/data.json').then(function(response) {
        return response.json()
    }).then(function(json) {
       console.log('parsed json ', json.listings);
        this.setState({listings: 'test string'});
    }).catch((error) => {
        console.log(error);
    })
}
render () {
    return (
        <ListingUser userData={this.state.listings} />
    );
}
}

    ReactDOM.render(
        <HelloWorld />,
        document.getElementById('example')
    );

Upvotes: 2

Views: 5099

Answers (2)

Justin Herrera
Justin Herrera

Reputation: 662

Inside of your .then() you are using the this keyword, and that's basically referring inside itself. To overcome this you have to use arrow function which will refer the value of this globally.

Using Normal Function

.then(function(response) {
   return response
   this.setState({listings: 'test string'}); // which will refer inside of this function
})

Using Arrow Function

.then((response) => {
   return response
   this.setState({listings: 'test string'}); // which will refer outside/global
})

Upvotes: 0

Michael Parker
Michael Parker

Reputation: 12966

The reason you're getting this error is because this doesn't refer to your component class inside of a promise. In order to use this.setState(), you'll need to bind the correct context of this.

fetch('./javascripts/data.json')
    .then(function(response) {
        return response.json();
    })
    .then(function(json) {
        console.log('parsed json ', json.listings);
        this.setState({listings: 'test string'});
    }.bind(this))
    .catch((error) => {
        console.log(error);
    });

You can also use an arrow function, which will lexically bind the correct value of this.

fetch('./javascripts/data.json')
    .then(response => {
        return response.json();
    })
    .then(json => {
        console.log('parsed json ', json.listings);
        this.setState({listings: 'test string'});
    })
    .catch(error => {
        console.log(error);
    });

Upvotes: 10

Related Questions