useEventListener
Strongly typed event-listener primitive for browser EventTargets.
About
Attach a listener to window, document, DOM elements, MediaQueryList, or any EventTarget, with overloads for the common browser event maps.
Example
import { useEventListener } from "rooks/experimental";
import { useRef, useState } from "react";
function Example() {
const ref = useRef<HTMLButtonElement | null>(null);
const [count, setCount] = useState(0);
useEventListener(
"click",
() => {
setCount((value) => value + 1);
},
{
target: ref,
}
);
return (
<button ref={ref} type="button">
Clicked {count} times
</button>
);
}Parameters
| Argument | Type | Default | Description |
|---|---|---|---|
eventName | string | required | Event name supported by the selected target. |
callback | (event) => void | required | Listener; the latest callback is invoked. |
options | object | required | Must include target; fields are described below. |
options.target accepts a Window, Document, HTML/SVG element, MediaQueryList, other EventTarget, a ref containing one of those targets, or null. listenerOptions defaults to {}, when to true, and isLayoutEffect to false.
Return value
Returns void.
Notes
options.targetmay be a direct target, a ref object, ornull.whendefaults totrue.isLayoutEffectdefaults tofalse.- Existing stable hooks such as
useWindowEventListenerstill work and now reuse this primitive internally.
Behavior and lifecycle
The listener is attached only while when is true and the resolved target exists. Changing the event name, target, listener options, or enablement removes the old listener before attaching the new one; unmount removes it as well. Callback changes do not require a rebind. Set isLayoutEffect only when the listener must be ready before paint.
Compatibility and accessibility
A null target and server rendering are safe no-ops. Browser support depends on the target and event. passive: true means the callback cannot cancel the event, and an externally aborted signal can remove the listener before React cleanup. Event listeners should complement native controls and keyboard semantics rather than replace them. See SSR and browser APIs.