最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Remove an event listener on React component unmount - Stack Overflow

programmeradmin3浏览0评论

I listen for window "scroll" events in one of my ponents. However when the ponent is unmounted, the scroll event listener is not being removed.

The following error is produced when a scroll event occurs after the ponent has been unmounted:

warning.js:36 Warning: setState(...): Can only update a mounted or mounting ponent. This usually means you called setState() on an unmounted ponent. This is a no-op. Please check the code for the TopNavDesktop ponent.

How can I properly remove this event listener?

Example code:

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

    this.state = {
      distanceScrolled: null
    }
  }

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

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

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

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

  render { ... } 
}

I listen for window "scroll" events in one of my ponents. However when the ponent is unmounted, the scroll event listener is not being removed.

The following error is produced when a scroll event occurs after the ponent has been unmounted:

warning.js:36 Warning: setState(...): Can only update a mounted or mounting ponent. This usually means you called setState() on an unmounted ponent. This is a no-op. Please check the code for the TopNavDesktop ponent.

How can I properly remove this event listener?

Example code:

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

    this.state = {
      distanceScrolled: null
    }
  }

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

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

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

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

  render { ... } 
}
Share Improve this question asked Oct 20, 2016 at 21:53 Don PDon P 63.7k121 gold badges318 silver badges447 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 12

When you remove the listener, you're creating a new function reference.

someFn.bind(this) === someFn.bind(this) will evaluate to false.

Instead, save the function in your constructor and use that reference:

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

    this.state = {
      distanceScrolled: null
    }

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

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

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

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

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

  render { ... } 
}

You should do this in this way:

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

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

By invoking second time this.handleScroll.bind(this) in ponentWillUnmount you creating new function instead of passing previous.

发布评论

评论列表(0)

  1. 暂无评论