【问题标题】:React this.setState is not a function反应 this.setState 不是一个函数
【发布时间】:2015-09-11 18:52:39
【问题描述】:

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

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    回调是在不同的上下文中进行的。您需要 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 年前。 ?
    • 我用箭头函数解决了这个问题。感谢您的帮助
    • 有人可以进一步详细说明“回调是在不同的上下文中进行的”是什么意思吗?
    • 神圣的。我花了几个小时,我可以做一个绑定?....至少它现在工作
    【解决方案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);
            }
    
        });
    

    【讨论】:

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

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

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

    或者您可以改用arrow function

    【讨论】:

      【解决方案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】:

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

          【讨论】:

          • 一个非常简洁的解决方案
          • 虽然在调用中将方法作为箭头函数调用,但也有同样的问题,但我想我必须像这样实现状态函数,而这正是我所做的
          【解决方案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));
           }
          

          【讨论】:

            【解决方案8】:

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

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

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

            【讨论】:

              【解决方案9】:

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

              【讨论】:

                【解决方案10】:

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

                【讨论】:

                  【解决方案11】:

                  如果你这样做但仍然有问题,我的问题是我调用了同名的两个变量。

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

                  【讨论】:

                    【解决方案12】:

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

                    【讨论】:

                      【解决方案13】:

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

                      【讨论】:

                        【解决方案14】:

                        我有同样的错误

                        TypeError: setState is not a function

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

                        代替

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

                        使用

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

                        方括号而不是大括号!

                        【讨论】:

                          【解决方案15】:

                          在我的例子中,问题是我将 state 和 setstate 作为 props 发送给子组件,但 setstate 中有错字

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 2015-08-06
                            • 1970-01-01
                            • 2019-05-01
                            • 2018-09-22
                            • 1970-01-01
                            • 1970-01-01
                            • 2017-07-27
                            相关资源
                            最近更新 更多