網站搜尋

javascript - React 的 this.setState 不是一個函數


在嘗試編寫與第三方 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>
        );
    }
});

答案#1

回調是在不同的上下文中進行的。你需要 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');

答案#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);
    }
});

答案#3

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

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

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

或者你可以改用 箭頭函數。

答案#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

使用箭頭函式,因為箭頭函式指向父級作用域,this 將可用。(bind 技術的替代方案)

答案#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));
 }