leo7r leo7r - 3 months ago 18
Javascript Question

Modify component state after a promise resolve

I want to modify a component's state (react native) after a promise is resolved.

Here is my code:

class Greeting extends Component{

constructor(props){
super(props);

this.state = {text: 'Starting...'};

var handler = new RequestHandler();
handler.login('email','password')
.then(function(resp){
this.setState({text:resp});
});
}

render(){
return (
<Text style={this.props.style}>
Resp: {this.state.text}
</Text>
);
}
}


But when the promise resolve, it throws the following error:

this.setState is not a function
TypeError: this.setState is not a function
at http://localhost:8081/index.android.bundle?platform=android&dev=true&hot=false&minify=false:1510:6
at tryCallOne (http://localhost:8081/index.android.bundle?platform=android&dev=true&hot=false&minify=false:25187:8)
at http://localhost:8081/index.android.bundle?platform=android&dev=true&hot=false&minify=false:25273:9
at JSTimersExecution.callbacks.(anonymous function) (http://localhost:8081/index.android.bundle?platform=android&dev=true&hot=false&minify=false:8848:13)
at Object.callTimer (http://localhost:8081/index.android.bundle?platform=android&dev=true&hot=false&minify=false:8487:1)
at Object.callImmediatesPass (http://localhost:8081/index.android.bundle?platform=android&dev=true&hot=false&minify=false:8586:19)
at Object.callImmediates (http://localhost:8081/index.android.bundle?platform=android&dev=true&hot=false&minify=false:8601:25)
at http://localhost:8081/index.android.bundle?platform=android&dev=true&hot=false&minify=false:7395:43
at guard (http://localhost:8081/index.android.bundle?platform=android&dev=true&hot=false&minify=false:7288:1)
at MessageQueue.__callImmediates (http://localhost:8081/index.android.bundle?platform=android&dev=true&hot=false&minify=false:7395:1)


How can I change the current Component state after a promise is resolved?

Answer

The callback has a different context than the object you are working with. For this reason, this is not what you think it is.


To solve this, you can use an arrow function, which keeps the surrounding context:

constructor(props){
    super(props);

    this.state = {text: 'Starting...'};

    var handler = new RequestHandler();
    handler.login('email','password')
        .then(resp => this.setState({text:resp}));
}

Alternatively, set the function context manually using bind():

constructor(props){
    super(props);

    this.state = {text: 'Starting...'};

    var handler = new RequestHandler();
    handler.login('email','password')
        .then(function(resp){
            this.setState({text:resp});
        }.bind(this));
}