javascript - React 的 this.setState 不是一個函數
在嘗試編寫與第三方 API 互動的應用程式時,不斷收到這個錯誤
TypeError:this.setState 不是一個函數
當我嘗試處理 API 回應時,我懷疑這個綁定有問題,但我無法找出如何修復它。這是我的組件代碼:
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 (
<div className="appMain">
<Header />
</div>
);
}
});
答案#1
回調是在不同的上下文中進行的。你需要 bind 到 this 才能在回調中訪問它:
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));
編輯:看起來你必須綁定 init 和 api 兩個調用:
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
你可以透過 ES6 箭頭函式來避免需要使用 .bind(this)。
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
React 建議在所有需要使用 class 的 this 的方法中綁定 this,而不是使用 self function 的 this。
constructor(props) {
super(props)
this.onClick = this.onClick.bind(this)
}
onClick () {
this.setState({...})
}
或者你可以改用 箭頭函數。
答案#4
你也可以在調用 api 方法之前,先保存對 this 的引用:
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');
},
答案#5
你只需要綁定你的事件
例如-
// place this code to your constructor
this._handleDelete = this._handleDelete.bind(this);
// and your setState function will work perfectly
_handleDelete(id){
this.state.list.splice(id, 1);
this.setState({ list: this.state.list });
// this.setState({list: list});
}
答案#6
使用箭頭函式,因為箭頭函式指向父級作用域,this 將可用。(bind 技術的替代方案)
答案#7
現在 ES6 有箭頭函數,如果你對 bind(this) 表達式感到困惑,它真的很有幫助,你可以試試箭頭函數
這就是我的做法。
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));
}
