我是React的新手,我正在尝试编写一个使用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>
);
}
});
答案 0 :(得分:272)
回调是在不同的上下文中进行的。您需要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');
答案 1 :(得分:107)
使用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);
}
});
答案 2 :(得分:37)
在调用this
方法之前,您还可以保存对api
的引用:
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');
},
答案 3 :(得分:9)
现在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));
}
答案 4 :(得分:9)
您只需要绑定您的活动
表示前 -
// 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});
}
答案 5 :(得分:8)
React建议将此绑定到需要使用text-align: center !important;
而不是自身class
的所有方法中。
function
或者您也可以改用constructor(props) {
super(props)
this.onClick = this.onClick.bind(this)
}
onClick () {
this.setState({...})
}
。
答案 6 :(得分:5)
Now in react with es6/7 you can bind function to current context with arrow function like this, make request and resolve promises like this :
listMovies = async () => {
const request = await VK.api('users.get',{fields: 'photo_50'});
const data = await request.json()
if (data) {
this.setState({movies: data})
}
}
With this method you can easily call this function in the componentDidMount and wait the data before render your html in your render function.
I don't know the size of your project but I personally advise against using the current state of the component to manipulate datas. You should use external state like Redux or Flux or something else for that.
答案 7 :(得分:5)
如果使用箭头功能,则无需将其分配给局部变量。箭头功能会自动进行绑定,您可以避免与范围相关的问题。
下面的代码说明了如何在不同情况下使用箭头功能
componentDidMount = () => {
VK.init(() => {
console.info("API initialisation successful");
VK.api('users.get',{fields: 'photo_50'},(data) => {
if(data.response){
that.setState({ //this available here and you can do setState
FirstName: data.response[0].first_name
});
console.info(that.state.FirstName);
}
});
}, () => {
console.info("API initialisation failed");
}, '5.34');
},
答案 8 :(得分:3)
此处上下文已更改。使用箭头功能保持React类的上下文。
VK.init(() => {
console.info("API initialisation successful");
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);
}
});
}, function(){
console.info("API initialisation failed");
}, '5.34');
答案 9 :(得分:2)
使用箭头函数,因为箭头函数指向父级作用域,因此将可用。 (替代绑定技术)
答案 10 :(得分:0)
如果您正在执行此操作,但仍然遇到问题,那么我的问题是我正在调用两个名称相同的变量。
我将
@Echo Off
Set "Name=%DATE%"
Set "Name=%Name:~-10,2%-%Name:~-7,2%-%Name:~-4%_job"
MD "C:\%Name%" 2>Nul
CD /D "C:\%Name%" || Exit /B
( Echo open 192.168.31.93
Echo *user*
Echo *password*
Echo binary
Echo cd *directory*
Echo mget *.*
Echo close
)>"ftp.txt"
FTP -i -s:ftp.txt
Del "ftp.txt" 2>Nul
Exit /B
作为从Firebase引入的对象,然后试图调用companies
-出于明显的原因,它无法正常工作。