删除React组件上的事件侦听器卸载

时间:2016-10-20 21:53:36

标签: javascript reactjs addeventlistener

我在听窗户"滚动"我的一个组件中的事件。但是,当组件卸载时,不会删除滚动事件侦听器。

在卸载组件后发生滚动事件时会产生以下错误:

  

warning.js:36警告:setState(...):只能更新已安装或   安装组件。这通常意味着你在一个上调用了setState()   未安装的组件。这是一个无操作。请检查代码   TopNavDesktop组件。

如何正确删除此事件侦听器?

示例代码:

class NavBar extends Component {
  constructor() {
    super();

    this.state = {
      distanceScrolled: null
    }
  }

  componentDidMount() {
    window.addEventListener('scroll', this.handleScroll.bind(this));
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScroll.bind(this));
  }

  handleScroll(e){
    const distanceScrolled = e.srcElement.body.scrollTop;

    this.setState({ distanceScrolled: distanceScrolled });
  }

  render { ... } 
}

2 个答案:

答案 0 :(得分:8)

删除侦听器时,您将创建一个新的函数引用。

someFn.bind(this) === someFn.bind(this)评估为false。

相反,请将该函数保存在构造函数中并使用该引用:

class NavBar extends Component {
  constructor() {
    super();

    this.state = {
      distanceScrolled: null
    }

    this.scrollFn = this.handleScroll.bind(this);
  }

  componentDidMount() {
    window.addEventListener('scroll', this.scrollFn);
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.scrollFn);
  }

  handleScroll(e){
    const distanceScrolled = e.srcElement.body.scrollTop;

    this.setState({ distanceScrolled: distanceScrolled });
  }

  render { ... } 
}

答案 1 :(得分:2)

你应该这样做:

componentDidMount() {
  this.listener = this.handleScroll.bind(this);
  window.addEventListener('scroll', this.listener);
}

componentWillUnmount() {
  window.removeEventListener('scroll', this.listener);
}

通过在this.handleScroll.bind(this)中调用第二次componentWillUnmount来创建新函数,而不是传递之前的函数。