反应this.setState不是一个函数

Iva*_*van 251 javascript reactjs

我是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>
        );
    }
});
Run Code Online (Sandbox Code Playgroud)

Dav*_*yon 311

回调是在不同的上下文中进行的.您需要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));
Run Code Online (Sandbox Code Playgroud)

编辑:看起来你必须绑定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');
Run Code Online (Sandbox Code Playgroud)

  • 可能还有2.5年前. (8认同)
  • 我用箭头函数来解决这个问题。谢谢您的帮助 (2认同)

goo*_*yun 119

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

    });
Run Code Online (Sandbox Code Playgroud)

  • 你的回答帮助了我:-)使用ES6类和RN 0.34,我找到了两种方法将"this"绑定到回调函数.1)`onChange = {(checked)=> this.toggleCheckbox()}`,2)`onChange = {this.toggleCheckbox.bind(this)}`. (4认同)
  • GMsoF,这两个解决方案有效,因为 a) 当你执行 `.bind(this)` 时,它将 `this` 的值设置为调用 `this.toggleCheckbox()` 的父上下文,否则 `this` 将引用到它实际执行的地方。b) 粗箭头解决方案之所以有效,是因为它保留了 `this` 的值,因此它通过不剧烈改变 `this` 的值来帮助您。在 JavaScript 中,`this` 只是指当前作用域,所以如果你写一个函数,`this` 就是那个函数。如果你在里面放了一个函数,`this` 就在那个子函数里面。粗箭头保持从哪里调用的上下文 (2认同)

use*_*463 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');
},
Run Code Online (Sandbox Code Playgroud)


uru*_*ong 21

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

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

 onClick () {
     this.setState({...})
 }
Run Code Online (Sandbox Code Playgroud)

或者你可以arrow function改用.


小智 12

你只需要绑定你的事件

为前

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

}
Run Code Online (Sandbox Code Playgroud)


小智 10

现在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));
 }
Run Code Online (Sandbox Code Playgroud)


小智 9

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


Yon*_*ong 8

我有同样的错误

TypeError: setState is not a function

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

代替

  const { state, setState } = React.useState(false);
Run Code Online (Sandbox Code Playgroud)

使用

  const [ state, setState ] = React.useState(false);
Run Code Online (Sandbox Code Playgroud)

括号而不是大括号!


Hem*_*ari 6

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

下面的代码说明了如何在不同情况下使用箭头功能

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');
 },
Run Code Online (Sandbox Code Playgroud)


Shu*_*pta 6

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


Que*_*guy 5

现在,在与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})
 }
}
Run Code Online (Sandbox Code Playgroud)

使用此方法,您可以轻松地在componentDidMount中调用此函数,并等待数据,然后再在render函数中呈现html。

我不知道您的项目规模,但我个人建议不要使用组件的当前状态来操纵数据。您应该使用Redux或Flux之类的外部状态。