可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm new in React and I'm trying to write an app working with an API. I keep getting this error: TypeError: this.setState is not a function when i try to handle the API response . I suspect it's something wrong with this binding but I can't figure out how to fix it. Here's the code of my component:
var AppMain = React.createClass({ getInitialState: function() { return{ FirstName: " " }; }, componentDidMount:function(){ VK.init(function(){ console.info("API initialisation successful"); VK.api('users.get',{fields: 'photo_50'},function(data){ if(data.response){ this.setState({ //the error happens here FirstName: data.response[0].first_name }); console.info(this.state.FirstName); } }); }, function(){ console.info("API initialisation failed"); }, '5.34'); }, render:function(){ return (
); } });
回答1:
The callback is made in a different context. You need to bind
to this
in order to have access inside the callback:
VK.api('users.get',{fields: 'photo_50'},function(data){ if(data.response){ this.setState({ //the error happens here FirstName: data.response[0].first_name }); console.info(this.state.FirstName); } }.bind(this));
EDIT: Looks like you have to bind both the init
and api
calls:
VK.init(function(){ console.info("API initialisation successful"); VK.api('users.get',{fields: 'photo_50'},function(data){ if(data.response){ this.setState({ //the error happens here FirstName: data.response[0].first_name }); console.info(this.state.FirstName); } }.bind(this)); }.bind(this), function(){ console.info("API initialisation failed"); }, '5.34');
回答2:
You can avoid the need for .bind(this) with an ES6 arrow function.
VK.api('users.get',{fields: 'photo_50'},(data) => { if(data.response){ this.setState({ //the error happens here FirstName: data.response[0].first_name }); console.info(this.state.FirstName); } });
回答3:
you could also save a reference to this
before you invoke the api
method:
componentDidMount:function(){ var that = this; VK.init(function(){ console.info("API initialisation successful"); VK.api('users.get',{fields: 'photo_50'},function(data){ if(data.response){ that.setState({ //the error happens here FirstName: data.response[0].first_name }); console.info(that.state.FirstName); } }); }, function(){ console.info("API initialisation failed"); }, '5.34'); },
回答4:
Now ES6 have arrow function it really helpful if you really confuse with bind(this) expression you can try arrow function
This is how I do.
componentWillMount() { ListApi.getList() .then(JsonList => this.setState({ List: JsonList })); } //Above method equalent to this... componentWillMount() { ListApi.getList() .then(function (JsonList) { this.setState({ List: JsonList }); }.bind(this)); }