Skip to content

noInvalidRemoveEventListener (JavaScript)

Language JavaScript (and super languages)
biome.json
{
"linter": {
"rules": {
"nursery": {
"noInvalidRemoveEventListener": "error"
}
}
}
}

Disallow passing a newly created function to removeEventListener().

removeEventListener() only removes a listener when it receives the exact same function that was passed to addEventListener(). An inline function, or the result of calling .bind(), creates a new function every time the code runs. Such a function was never added as a listener, so the call does nothing and the original listener stays attached.

window.removeEventListener("click", listener.bind(window));
code-block.js:1:46 lint/nursery/noInvalidRemoveEventListener ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ The function returned by .bind() is never removed by removeEventListener().

> 1 │ window.removeEventListener("click", listener.bind(window));
│ ^^^^
2 │

ℹ .bind() returns a new function every time it's called, so it can't be the same function that was passed to addEventListener(). The original listener stays attached.

ℹ Store the listener in a variable or property, and pass that same reference to both addEventListener() and removeEventListener().

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

window.removeEventListener("click", () => {});
code-block.js:1:37 lint/nursery/noInvalidRemoveEventListener ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ This inline function is never removed by removeEventListener().

> 1 │ window.removeEventListener("click", () => {});
│ ^^^^^
2 │

ℹ An inline function is a new function, so it can't be the same function that was passed to addEventListener(). The original listener stays attached.

ℹ Store the listener in a variable or property, and pass that same reference to both addEventListener() and removeEventListener().

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

window.removeEventListener("click", function () {});
code-block.js:1:37 lint/nursery/noInvalidRemoveEventListener ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ This inline function is never removed by removeEventListener().

> 1 │ window.removeEventListener("click", function () {});
│ ^^^^^^^^^^^
2 │

ℹ An inline function is a new function, so it can't be the same function that was passed to addEventListener(). The original listener stays attached.

ℹ Store the listener in a variable or property, and pass that same reference to both addEventListener() and removeEventListener().

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

class MyElement extends HTMLElement {
handler() {}
disconnectedCallback() {
this.removeEventListener("click", this.handler.bind(this));
}
}
code-block.js:5:56 lint/nursery/noInvalidRemoveEventListener ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ The function returned by .bind() is never removed by removeEventListener().

4 │ disconnectedCallback() {
> 5 │ this.removeEventListener("click", this.handler.bind(this));
│ ^^^^
6 │ }
7 │ }

ℹ .bind() returns a new function every time it's called, so it can't be the same function that was passed to addEventListener(). The original listener stays attached.

ℹ Store the listener in a variable or property, and pass that same reference to both addEventListener() and removeEventListener().

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

const listener = () => {};
window.addEventListener("click", listener);
window.removeEventListener("click", listener);
window.removeEventListener("click", getListener());
class MyElement extends HTMLElement {
constructor() {
super();
this.handler = this.handler.bind(this);
}
handler() {}
disconnectedCallback() {
this.removeEventListener("click", this.handler);
}
}