ChatGPT解决这个技术问题 Extra ChatGPT

反应 this.setState 不是一个函数

我是 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>
        );
    }
});

D
Davin Tryon

回调是在不同的上下文中进行的。您需要 bindthis 才能访问回调内部:

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));

编辑:看起来您必须同时绑定 initapi 调用:

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');

@TravisReeder,不。教程中没有提到绑定。
大概是2.5年前。 😁
我使用箭头函数来解决这个问题。谢谢您的帮助
有人可以进一步详细说明“回调是在不同的上下文中进行的”是什么意思吗?
圣。我花了几个小时,我本来可以做一个绑定?....至少现在可以工作了
g
goodhyun

您可以通过 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);
        }

    });

这很好用。事实上,函数的关键字不应该出现在 es6 的文件中。
您的回答帮助了我:-) 使用 ES6 类和 RN 0.34,我找到了两种将“this”绑定到回调函数的方法。 1)onChange={(checked) => this.toggleCheckbox()},2)onChange={this.toggleCheckbox.bind(this)}
只要您不需要支持旧浏览器,这很好。
完美解决方案
GMsoF,这两个解决方案之所以有效,是因为 a) 当您执行 .bind(this) 时,它将 this 的值设置为从中调用 this.toggleCheckbox() 的父上下文,否则 this 将引用它实际执行的位置。 b) 胖箭头解决方案之所以有效,是因为它保留了 this 的值,因此它通过不剧烈改变 this 的值来帮助您。在 JavaScript 中,this 只是指当前作用域,所以如果你写一个函数,this 就是那个函数。如果您在其中放置一个函数,则 this 在该子函数中。粗箭头保留调用位置的上下文
u
uruapanmexicansong

React 建议在所有需要使用 class 的 this 而不是 self function 的方法中绑定 this。

constructor(props) {
    super(props)
    this.onClick = this.onClick.bind(this)
}

 onClick () {
     this.setState({...})
 }

或者您可以改用 arrow function


愿意分享一个例子,如何使用箭头函数来解决这个问题?
u
user2954463

您还可以在调用 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');
},

g
g8bhawani

你只需要绑定你的事件

对于前

// 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});

}

P
Pranav Kapoor

使用箭头函数,因为箭头函数指向父范围,这将是可用的。 (替代绑定技术)


一个非常简洁的解决方案
虽然在调用中将方法作为箭头函数调用时也有同样的问题,但我想我必须这样实现状态函数,而这正是我所做的
S
Sameel

现在 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));
 }

H
Hemadri Dasari

如果您使用箭头函数,则无需将其分配给局部变量。箭头函数自动绑定,您可以避免与范围相关的问题。

下面的代码解释了如何在不同的场景中使用箭头函数

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');
 },

Q
Quentin Malguy

现在在与 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 这样的外部状态或其他东西。


S
Shubham Gupta

在这里,这个上下文正在发生变化。使用箭头函数来保持 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');

Y
Yong

我有同样的错误

TypeError: setState is not a function

但原因很愚蠢。在这里发布它作为回应,希望能拯救可能犯同样错误的人。

代替

  const { state, setState } = React.useState(false);

利用

  const [ state, setState ] = React.useState(false);

方括号而不是大括号!


L
LukeVenter

如果您正在这样做并且仍然遇到问题,那么我的问题是我将两个变量称为同名。

我将 companies 作为从 Firebase 引入的对象,然后尝试调用 this.setState({companies: companies}) - 由于显而易见的原因它无法正常工作。


t
tohidmahmoudvand

使用 from 箭头函数来处理动作。


E
Elikill58

这主要是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"
[...]

H
HibaHasan

就我而言,问题是我将 state 和 setstate 作为 props 发送给子组件,但 setstate 中有错字