removeEventListener removes an event listener added with
addEventListener. However, there are a number of gotchas to watch out for in order to correctly remove an event listener.
Instructor: [0:01] In order to remove an event listener from an event target, we use the removeEventListener() API. In order to correctly remove an event listener, you need to use the four uniquely identifying attributes of an event listener that you used with your addEventListener() call. That is the event target, the event name, the listener reference and the capture value.
[0:25] When it comes to the capture value that you provide to removeEventListener, it does not matter how you express the capture value, only that it is the equivalent value that you used with addEventListener. Unfortunately, the removeEventListener API gives no indication as to whether a removal was successful. If you mess anything up, you won't know about it.
[0:51] There are a few gotchas I've seen when trying to remove event listeners with removeEventListener. Firstly, you need to pass in the same event listener reference to removeEventListener as you did to addEventListener in order to remove it.
[1:06] I've seen it come up a few times where a function is provided to removeEventListener that looks the same as the one that you've added with addEventListener. However, they're two different functions with two different references.
[1:21] In this case, the removeEventListener call will not remove the original onclick function. You'll need to ensure that the same reference is passed to removeEventListener as you provided to addEventListener in order to successfully unbind the event listener.
[1:39] This gotcha seems to be more common when using arrow functions. Again, I'm providing a function that looks the same to addEventListener and removeEventListener, but they are different functions with different references. When I click My Button, click is being logged to the console because my original event handler is not being unbound.
[2:00] Here, I am lifting my arrow function up, assigning it to the onclick constant, so that I can pass in the same reference to addEventListener and removeEventListener. Now, when I click the button, click is no longer being logged to the console.
[2:14] Generally speaking, it's pretty dangerous to create functions in the second argument to addEventListener. This is because you lose access to the function reference after you have created it. Here, I've called addEventListener, and I have no way of getting a reference to this function, so I can't remove it correctly.
[2:34] Here, I'm creating a named onclick function in my second argument to addEventListener, but then when I go to call removeEventListener, I don't have a reference to that onclick function anymore. If I'm inside the onclick function, I can't get access to it in order to remove it.
[2:50] Generally, I do not create my event listener functions inside of my addEventListener call. I'll usually create it at some layer above so that I can easily share it with the removeEventListener if I need to.
[3:03] Another gotcha with the removeEventListener is not passing in the correct capture value. Here, I'm adding an event listener in the capture phase. Then, here, I've forgotten to specify a capture value, which means it's going to use the default capture value as false, so this will not unbind this addEventListener. When I click My Button, I can see that clicked is being logged out.
[3:26] This mistake is surprisingly easy to do when your addEventListener and removeEventListener calls are not right next to each other. You might come along to an event listener and think, "Oh, this should be a capture event listener," and so you add in a capture flag.
[3:39] Then you forget to update your removeEventListener call, and now, your event listener will no longer be removed when you expect it to. This bug can be super hard to detect, as removeEventListener gives no indication of whether the unbinding was successful.
[3:55] In order to avoid the gotchas associated with removeEventListener, I often create this little helper. Here, I have a function called bind() that accepts an event target and an object containing the event type, our listener and options. It then calls target.addEventListener, providing in the type, listener and options.
[4:16] It then returns a function called unbind(), which calls target.removeEventListener, passing in the type, listener and options. The power of this helper is, the four uniquely identifying pieces of an event listener that you use with your addEventListener call are always used with a matching removeEventListener, ensuring that you are always correctly unbinding an event listener.
[4:41] If we come back to my application, I can now import my bind helper. Here, I'm calling my bind helper, passing in my button event target and then an object containing the event type, the listener, which, in this case, is my onclick function, and then an options object, where I'm setting capture to false.
[5:00] To unbind that event, all I need to do is call the unbind function, and I know I'm always going to clean that up properly. If I click on My Button, I can see that nothing's being logged to the console.
[5:13] This little bind helper also unlocks safer usage of functions defined inside your binding, because the bind function helper has access to that function, so it can correctly pass it into removeEventListener. Rather than writing this little bind helper for every new project, I've done it for you and created a bind-event-listener package on npm that you can install and use just like this.
[5:39] My bind-event-listener package also has a bindAll variant that takes an event target as well as an array of bindings. It returns you back a single function that, when you execute it, will unbind all of these event listeners in the same go. Personally, I found it to be pretty useful.
At 2.47 when removeEventListener is inside addListener onClick function, it remove the listener but clicked is logged once no? PS: you've made such a great course -)