Skip to content

How to remove event callback with parameters

I have a web application that page A has video, and page B doesn’t. The video has the onended event when it finishes video playback. I tried to remove the event before the component unmounts with removeEventListener, or the video ended event will be fired after I switched to page B.

However, I cannot find the proper way to remove callback with parameters. I used the arrow function and bind to pass parameters, but these two methods made event removal impossible.

componentDidMount() {
  // 1st trial: anonymous function cannot be removed
  this.video.onended = () => this.videoOnEndedCallback(params);
  // 2nd trial: bind() creates new function, cannot be referenced either
  this.video.onended = this.videoOnEndedCallback.bind(this, params);
}

componentWillUnmount() {
  this.video.removeEventListener('ended', this.videoOnEndedCallback);
}

Lastly, I set the onended to null, and it works.

componentWillUnmount() {
  this.video.onended = null;
}

Question

If setting onended to null equals the effect of removeEventListener?

If not, is there any other proper way to remove callback with parameters?

Answer

If the event listener was set using the named event property (.onended in this case), it can be changed by reassigning and removed by setting it to null. (Only a single listener per event can be set up this way.)

The other way, .addEventListener(), can register multiple event listeners for the same event, cannot be changed and can only be removed by .removeEventListener() (requires a reference to the set listener).

These two ways work along with each other, but either way, you have to choose the method for each listener to be used for adding/changing/removing that listener.

In your case, it’s easier to use the event listener property, as if you .bind() the function, you won’t have the reference to the new function, so you won’t be able to remove it by .removeEventListener().

On the other hand, if you store its reference, you can also use the .addEventListener()/.removeEventListener() methods:

constructor(){
  this.boundVideoOnEndedCallback = this.videoOnEndedCallback.bind(this, params); //You can also use the arrow-function-version here
}
componentDidMount() {
  this.video.addEventListener('ended', this.boundVideoOnEndedCallback)
}

componentWillUnmount() {
  this.video.removeEventListener('ended', this.boundVideoOnEndedCallback);
}