ReactJS - this.functionname is not a function

假如想象 提交于 2019-12-11 11:49:04

问题


I have a listener setup in my componentDidMount:

updateBasketTotal: function() {
    BasketService.getBasketTotal(function(data){
        this.setState({
            selectedPeopleCount: data.TotalMembers
        });
    }.bind(this));
},

componentDidMount: function() {
    this.updateBasketTotal();
    this.subscribeToChannel(basketChannel,"selectAll",this.listenerSelectAll);
    this.subscribeToChannel(basketChannel,"removePersonFromBasket",this.listenerRemovePersonFromBasket);
    this.subscribeToChannel(basketChannel,"addPersonToBasket",this.listenerAddPersonToBasket);
    this.subscribeToChannel(basketChannel,"addArrayToBasket",this.listenerAddArrayToBasket);
},

listenerAddArrayToBasket: function(data){
    BasketService.addPerson(data.arrayToPush,function(){
        this.updateBasketTotal();
    });
},
listenerAddPersonToBasket: function(data){
    BasketService.addPerson(data.personId,function(){
        this.updateBasketTotal();
    });
},
listenerRemovePersonFromBasket: function(data){
    BasketService.removePerson(data.personId,function(){
       this.updateBasketTotal();
    });
},
listenerSelectAll: function(data){
    BasketService.selectAll(data.selectAll, function () {
        this.updateBasketTotal();
    });
}

However, if I publish a message when I'm not on this page, I get an error:

this.updateBasketTotal is not a function

Can anyone please tell me how I can use this.updateBasketTotal?

I think its a problem with 'this' but not sure how to fix it. Thanks in advance

UPDATE:

Have tried adding bind() to the listener:

    listenerAddPersonToBasket: function(data){
    BasketService.addPerson(data.personId,function(){
        this.updateBasketTotal();
    }.bind());
},

But no joy, any ideas?


回答1:


I assume your component is unsubscribing to those channels in componentWillUnmount to avoid resource leaks and duplicate subscriptions.

The asynchronous callbacks should call isMounted to ensure the component is still mounted before attempting anything else.

BasketService.selectAll(data.selectAll, function () {
    if (this.isMounted()) {
        this.updateBasketTotal();
    }
}.bind(this));

I don't know if the isMounted check will solve your problem since that may also not be a function anymore. If it isn't, you might consider adding your own property to track whether the component is mounted or not and check that rather calling a function.




回答2:


listenerAddArrayToBasket: function(data) {
    var _this = this;
    BasketService.addPerson(data.arrayToPush,function() {
        _this.updateBasketTotal();
    });
}

or

listenerAddArrayToBasket: function(data) {
    BasketService.addPerson(data.arrayToPush,function() {
        this.updateBasketTotal();
    }.bind(this));
}

React does not bind context by default, you have to do it yourself. In your example this would refer to callback function, not to react object. You can either assign react context to a variable and use it inside your callback, or bind context directly to callback.

Here is the great article explaining contexts in JavaScript

Also in ES6 it's possible to use double arrow declaration

class SomeComponent extends React.Component {

  updateBasketTotal() {
    ....
  }

  lisneterAddArrayToBasket() {
    BasketService.addPerson(data.arrayToPush, () => {
      this.updateBasketTotal()
    })
  }

}

You can use babel to compile your ES6 code to old plain ES5 :)



来源:https://stackoverflow.com/questions/31740875/reactjs-this-functionname-is-not-a-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!