Home > front end >  JavaScript remove event listener with params
JavaScript remove event listener with params

Time:11-02

I am adding an event listener which needs the event properties as well as other parameters

    document.body.addEventListener("click", (e) =>
        listenForMembersOpen(e, buttonReplacement, openEditModal)
    );

I need to remove this event listener when my component unmounts but running:

    document.body.removeEventListener("click", (e) =>
        listenForMembersOpen(e, buttonReplacement, openEditModal)
    );

doesn't seem to get the job done. I'm thinking it is because the function declaration within the event listener. Any advice on how I can remove the event lister shown?

export function addListenersForButtonReplacement(buttonReplacement, openEditModal) {
    document.body.addEventListener("click", (e) =>
        listenForMembersOpen(e, buttonReplacement, openEditModal)
    );
    document.body.addEventListener("keydown", (e) =>
        listenForMembersOpen(e, buttonReplacement, openEditModal)
    );
}

CodePudding user response:

yeah. you need to have a single function otherwise javascript won't be able to find the function reference

    function listener (e) {
       listenForMembersOpen(e, buttonReplacement, openEditModal)
    }

    document.body.addEventListener("click", listener);    
    document.body.removeEventListener("click", listener);

CodePudding user response:

If you've ever tried comparing equality for an object, you know that:

const a = { v: 1 };
const b = { v: 1 };

a !== b
a != b
a === a
b === b

And that applies to functions as well.

When you call addEventListener, it doesn't toString() the input function, and when the event listener is removed, check for equality. Instead, it stores the "reference", the function you passed to as an argument, and compares that.

The way you'd use it, then, is by passing the same variable to removeEventListener as to addEventListener, like this:

// create a separate function to handle the event
const eventHandler = (e) => listenForMembersOpen(e, buttonReplacement, openEditModal);

document.body.addEventListener("click", eventHandler);

// later...
document.body.removeEventListener("click", eventHandler);

Simply passing the same function body content (meaning when you toString() it the value will be the same) will not be recognized as the same event listener.


In your context, you'll need to export that function to be used elsewhere, perhaps by returning that value from the exported function, like this:

export function addListenersForButtonReplacement(buttonReplacement, openEditModal) {
  const eventHandler = (e) => listenForMembersOpen(e, buttonReplacement, openEditModal);
  document.body.addEventListener("click", eventHandler);
  document.body.addEventListener("keydown", eventHandler);

  // "export" it by returning:
  return eventHandler;
}

Later when you're using it elsewhere...

import { addListenersForButtonReplacement } from "./somewhere";

// later...
const evFn = addListenersForButtonReplacement(/* ... */);

// later... (we have the same "reference" to the function)
document.body.removeEventListener("click", evFn);
document.body.removeEventListener("keydown", evFn);
  • Related