当前位置: 首页 > 面试题库 >

商店的更改侦听器未在componentWillUnmount上移除?

东郭兴学
2023-03-14
问题内容

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

我已经发现这是因为未将挂钩所钩挂的changelistener从商店中删除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)给addListener。bind返回与此绑定的
函数。然后,您将放弃对该绑定函数的引用。然后,您尝试删除由绑定调用创建的另一个 函数,这是一个空操作,因为从未添加过。

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

@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());

  }

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

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

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

因为_onChange的初始值设定项是在构造函数的上下文中调用的,所以arrow函数会自动绑定this到类实例,因此您可以将其this._onChange作为事件处理程序传递而无需手动绑定它。



 类似资料:
  • 在我的代码中,如果用户在ComboBox 2中输入值,它将反映在TextField中,但是如果用户从ComboBox 1的下拉列表中选择,而不更改ComboBox 2中的值,那么TextField中的值将保持不变,它不会更改。我做错了吗? 测试2。txt:1任何帮助都将不胜感激!

  • 问题内容: 我希望消息框在用户更改文本字段中的值后立即显示。目前,我需要按Enter键才能弹出消息框。我的代码有什么问题吗? 任何帮助,将不胜感激! 问题答案: 将侦听器添加到为您自动创建的基础文档中。

  • 问题内容: 我想一种添加到我当过用户更改的,它的值,应用程序在控制台上打印的东西。 我进行了搜索,发现以下非常相似的问题:JTextField的值更改侦听器 提到的问题的答案非常清楚和有效,但是不幸的是,它仅对(Not )有用,因为它说您应该像这样使用DocumentListener: 但是在JavaFX的TextField中,您无法执行此操作。所以?解决办法是什么? (使用代码进行描述可能会很好

  • 问题内容: 每当尝试从中进行选择时,我都试图触发一个事件。 我遇到的问题是没有明显的方法。 我尝试使用,但从未触发。 没有覆盖的模型,我没有想法。 如何通知有关 选择更改的通知? 编辑:我要道歉。事实证明,我使用的是行为不佳的子类,但由于你的回答是好的,因此我将保留该问题。 问题答案: 它应该响应,如下所示: 正确地指出了也可以。但是,你可能会得到 ,一个用于取消选择先前选择的项目,另一个用于选择

  • 问题内容: 我希望在用户更改文本字段中的值后立即显示消息框。目前,我需要按Enter键才能弹出消息框。我的代码有什么问题吗? 任何帮助,将不胜感激! 问题答案: 将侦听器添加到为你自动创建的基础文档中。

  • 本文向大家介绍Android 侦听SharedPreferences更改,包括了Android 侦听SharedPreferences更改的使用技巧和注意事项,需要的朋友参考一下 示例 请注意: 仅当添加或更改值时,侦听器才会触发,设置相同的值将不会调用它; 侦听器需要保存在成员变量中,而不是匿名类,因为registerOnSharedPreferenceChangeListener它使用弱引用进