我是 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>
);
}
});
回调是在不同的上下文中进行的。您需要 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');
您可以通过 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);
}
});
onChange={(checked) => this.toggleCheckbox()}
,2)onChange={this.toggleCheckbox.bind(this)}
。
.bind(this)
时,它将 this
的值设置为从中调用 this.toggleCheckbox()
的父上下文,否则 this
将引用它实际执行的位置。 b) 胖箭头解决方案之所以有效,是因为它保留了 this
的值,因此它通过不剧烈改变 this
的值来帮助您。在 JavaScript 中,this
只是指当前作用域,所以如果你写一个函数,this
就是那个函数。如果您在其中放置一个函数,则 this
在该子函数中。粗箭头保留调用位置的上下文
React 建议在所有需要使用 class
的 this 而不是 self function
的方法中绑定 this。
constructor(props) {
super(props)
this.onClick = this.onClick.bind(this)
}
onClick () {
this.setState({...})
}
或者您可以改用 arrow function
。
您还可以在调用 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');
},
你只需要绑定你的事件
对于前
// 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});
}
使用箭头函数,因为箭头函数指向父范围,这将是可用的。 (替代绑定技术)
现在 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));
}
如果您使用箭头函数,则无需将其分配给局部变量。箭头函数自动绑定,您可以避免与范围相关的问题。
下面的代码解释了如何在不同的场景中使用箭头函数
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');
},
现在在与 es6/7 的反应中,您可以使用像这样的箭头函数将函数绑定到当前上下文,发出请求并解决这样的承诺:
listMovies = async () => {
const request = await VK.api('users.get',{fields: 'photo_50'});
const data = await request.json()
if (data) {
this.setState({movies: data})
}
}
使用此方法,您可以轻松地在 componentDidMount 中调用此函数,并在渲染函数中渲染 html 之前等待数据。
我不知道您的项目的大小,但我个人建议不要使用组件的当前状态来操作数据。你应该使用像 Redux 或 Flux 这样的外部状态或其他东西。
在这里,这个上下文正在发生变化。使用箭头函数来保持 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');
我有同样的错误
TypeError: setState is not a function
但原因很愚蠢。在这里发布它作为回应,希望能拯救可能犯同样错误的人。
代替
const { state, setState } = React.useState(false);
利用
const [ state, setState ] = React.useState(false);
方括号而不是大括号!
如果您正在这样做并且仍然遇到问题,那么我的问题是我将两个变量称为同名。
我将 companies
作为从 Firebase 引入的对象,然后尝试调用 this.setState({companies: companies})
- 由于显而易见的原因它无法正常工作。
使用 from 箭头函数来处理动作。
这主要是react,react-dom和酶之间的不兼容问题。
尝试像我一样安装以下内容来解决问题:
[...]
"react": "^18.0.0-beta-f320ef88f-20211116",
"react-dom": "16.14.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.6"
[...]
就我而言,问题是我将 state 和 setstate 作为 props 发送给子组件,但 setstate 中有错字
不定期副业成功案例分享