8

I'm new to react so I'm sure I'm missing something basic. I'm getting undefined for this, and therefore cannot read property 'setState' attempting to set state within the return of a function that calls fetch, what am I doing wrong? Note I call MyAction from an onClick and the response data is fine.

var ItemComponent = React.createClass({

    getInitialState: function() {
        return {
            the_message: "call that API!"
        };
    },

    doFetch: function() {
        var obj = {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            }
        };
        return fetch('http://localhost:1337/site/test', obj)
            .then(function(response) {
                return response.json();
            }).then(function(data) {
                return data;
            }).catch((error) => {
                console.error(error);
            });
    },

    MyAction: function() {
        this.doFetch().then(function(response){
            this.setState({
                the_message: response.message
            });
        })
    },

    render: function() {
        return (
            <div>
                <div>{this.props.title}</div><br></br>
                <div>{this.props.price}</div><br></br>
                <div onClick={this.MyAction}>{this.props.qty}</div>
            </div>
        );
    }
});
1

3 Answers 3

11

Use arrow function (() => {}) which keeps the last scope (this) as it is .

MyAction: function(){
    this.doFetch().then((response) => {
        this.setState({
            the_message: response.message
        });
    });
},
Sign up to request clarification or add additional context in comments.

1 Comment

what about function component, what will be the syntax then
8

Your inner promise resolution function won't have this context. One way to fix it:

MyAction: function(){
    this.doFetch().then(function(response){
        this.setState({
            the_message: response.message
        });
    }.bind(this))
},

Read more about that on this StackOverflow question.

2 Comments

Pefect, your secondly fixed it, I'm not sure what you are suggesting in your first item, as that's my code unchanged? In any case I'm accepting your answer as soon as it lets me (5 min). Side question, I should really be using ES6 syntax yeah? after getting started on some tutorials, I think this syntax is long toothed.
Double whoops, I just assumed you were using ES6 classes, the first update was irrelevant. Please close your question as a duplicate.
3

A simple .bind(this) would solve the issue:

render: function() {
return (
<div>
<div>{this.props.title}</div><br></br>
<div>{this.props.price}</div><br></br>
<div onClick={this.MyAction.bind(this)}>{this.props.qty}</div>
</div>
);

By adding .bind(this) you keep the scope within your function.

1 Comment

You create a new function on every render doing it like this. It's better to bind the handler in the constructor or create an arrow function inside the class.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.