gpt4 book ai didi

reactjs - 商店的更改监听器未在 componentWillUnmount 上删除?

转载 作者:行者123 更新时间:2023-12-03 13:25:18 25 4
gpt4 key购买 nike

我正在reactjs-flux上编写一个简单的应用程序,一切正常,除了我收到reactjs的警告,告诉我我正在对未安装的组件调用setState。

我发现这是因为组件所 Hook 的变更监听器没有从 componentWillUnmount 上的存储中删除。我知道这一点是因为当我从 Eventemitter 打印监听器列表时,我看到应该被销毁的监听器仍然存在,并且随着我多次安装/卸载同一组件,该列表会变得更大。

我从我的 BaseStore 粘贴代码:

import Constants from '../core/Constants';
import {EventEmitter} from 'events';

class BaseStore extends EventEmitter {
// Allow Controller-View to register itself with store
addChangeListener(callback) {
this.on(Constants.CHANGE_EVENT, callback);
}

removeChangeListener(callback) {
this.removeListener(Constants.CHANGE_EVENT, callback);
}

// triggers change listener above, firing controller-view callback
emitChange() {
this.emit(Constants.CHANGE_EVENT);
}
}

export default BaseStore;

我粘贴了遇到此错误的组件中的相关代码(尽管所有组件都会发生这种情况):

@AuthenticatedComponent
class ProductsPage extends React.Component {
static propTypes = {
accessToken: PropTypes.string
};

constructor() {
super();
this._productBatch;
this._productBatchesNum;
this._activeProductBatch;
this._productBlacklist;
this._searchById;
this._searchingById;
this.state = this._getStateFromStore();
}

componentDidMount() {
ProductsStore.addChangeListener(this._onChange.bind(this));
}

componentWillUnmount() {
ProductsStore.removeChangeListener(this._onChange.bind(this));
}

_onChange() {
this.setState(this._getStateFromStore());
}
}

此时此刻,这让我非常抓狂。有什么想法吗?

谢谢!

最佳答案

简短版本:expect(f.bind(this)).not.toBe(f.bind(this));

更长的解释:

问题的原因是EventEmitter.removeListener要求您传递之前已注册的函数 EventEmitter.addListener 。如果您传递对任何其他函数的引用,则它是静默无操作。

在您的代码中,您正在传递 this._onChange.bind(this)添加监听器。 bind返回一个绑定(bind)到此的函数。然后,您将丢弃对该绑定(bind)函数的引用。然后,您尝试删除另一个由绑定(bind)调用创建的函数,但它是一个无操作,因为它从未添加过。

React.createClass 自动绑定(bind)方法。在 ES6 中,您需要在构造函数中手动绑定(bind):

@AuthenticatedComponent
class ProductsPage extends React.Component {
static propTypes = {
accessToken: PropTypes.string
};

constructor() {
super();
this._productBatch;
this._productBatchesNum;
this._activeProductBatch;
this._productBlacklist;
this._searchById;
this._searchingById;
this.state = this._getStateFromStore();
// Bind listeners (you can write an autoBind(this);
this._onChange = this._onChange.bind(this);
}

componentDidMount() {
// listener pre-bound into a fixed function reference. Add it
ProductsStore.addChangeListener(this._onChange);
}

componentWillUnmount() {
// Remove same function reference that was added
ProductsStore.removeChangeListener(this._onChange);
}

_onChange() {
this.setState(this._getStateFromStore());
}

有多种简化绑定(bind)的方法 - 您可以使用 ES7 @autobind方法装饰器(例如 npm 上的 autobind-decorator),或者编写一个在构造函数中使用 autoBind(this); 调用的 autoBind 函数.

在 ES7 中,您(希望)能够使用类属性来获得更方便的语法。如果您愿意,您可以在 Babel 中启用此功能,作为第一阶段提案的一部分 http://babeljs.io/docs/plugins/transform-class-properties/ 。然后,您只需将事件监听器方法声明为类属性而不是方法:

_onChange = () => {
this.setState(this._getStateFromStore());
}

因为 _onChange 的初始化程序是在构造函数的上下文中调用的,所以箭头函数自动绑定(bind) this到类实例,这样你就可以传递 this._onChange作为事件处理程序,无需手动绑定(bind)它。

关于reactjs - 商店的更改监听器未在 componentWillUnmount 上删除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32121231/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com