eslint-react icon indicating copy to clipboard operation
eslint-react copied to clipboard

[bug] no-leaked-event-listener false positive when using AbortSignal via wrapper hook

Open TrevorBurnham opened this issue 2 months ago • 3 comments

Describe the bug

I use this convenience wrapper for when I want to add an event listener in a useEffect and remove it on cleanup:

/**
 * A wrapper around `useEffect` that automatically cleans up an event listener using AbortSignal.
 * Usage:
 *
 * useEventEffect((signal) => {
 *   window.addEventListener("scroll", () => {
 *     // do something
 *   }, { signal });
 * });
 */
export const useEventEffect = (
  effectHandler: (signal: AbortSignal) => void,
  deps: DependencyList,
) => {
  useEffect(() => {
    const controller = new AbortController();
    effectHandler(controller.signal);
    return () => {
      controller.abort();
    };
  }, deps); // eslint-disable-line react-hooks/exhaustive-deps
};

When I use addEventListener within that hook, it gets flagged by the rule, even though the listener is cleaned up by aborting the signal.

Reproduction

No response

Expected behavior

I think it would be reasonable to ignore any addEventListener call where signal is used. I see that signal is supported by the rule: #838 But the rule seems to be looking for the abort call within a limited scope.

I'd suggest that passing in a signal should be sufficient to satisfy the rule, since the linter can't reliably determine whether that signal will be aborted at the appropriate time.

Platform and versions

* @eslint-react/eslint-plugin v2.0.6
* Node.js v22.17.1

Stack trace


Additional context

No response

TrevorBurnham avatar Oct 15 '25 17:10 TrevorBurnham

Another false positive for this rule is BackHandler from react-native.

BackHandler.addEventListener returns a remove method, but the rules complains when it is used.

SuperKXT avatar Nov 09 '25 10:11 SuperKXT

I'd suggest that passing in a signal should be sufficient to satisfy the rule, since the linter can't reliably determine whether that signal will be aborted at the appropriate time.

I agree to this change. A PR is welcome.

Rel1cx avatar Nov 15 '25 13:11 Rel1cx

Another false positive for this rule is BackHandler from react-native.

BackHandler.addEventListener returns a remove method, but the rules complains when it is used.

@SuperKXT Thank you for reporting it. This should be worth opening a separate issue.

Rel1cx avatar Nov 15 '25 13:11 Rel1cx