useEventListener
zyeon/use-event-listenerFreeHook
A type-safe window/document/element event listener hook with a latest-ref handler — zero rebinds on handler change, never stale.
Install it
npx shadcn@latest add https://ui.zyeon.ai/r/use-event-listener.jsonSource
1"use client"23import * as React from "react"45export interface UseEventListenerOptions {6 /** Passed straight through as the native addEventListener `passive`. */7 passive?: boolean8 /** Passed straight through as the native addEventListener/removeEventListener `capture`. */9 capture?: boolean10}1112type TargetRef<T extends HTMLElement> = React.RefObject<T | null>1314// Overload 1: no target, or window passed explicitly — event names map to WindowEventMap.15export function useEventListener<K extends keyof WindowEventMap>(16 eventName: K,17 handler: (event: WindowEventMap[K]) => void,18 options?: UseEventListenerOptions & { target?: Window },19): void2021// Overload 2: document as the target — event names map to DocumentEventMap.22export function useEventListener<K extends keyof DocumentEventMap>(23 eventName: K,24 handler: (event: DocumentEventMap[K]) => void,25 options: UseEventListenerOptions & { target: Document },26): void2728// Overload 3: an element RefObject as the target — event names map to29// HTMLElementEventMap, and T is inferred from the ref at the call site (say30// RefObject<HTMLDivElement>).31// Note: the effect depends on the ref object itself (stable identity). If .current32// is null when the effect runs, nothing is bound this round and nothing re-binds33// later — for a conditionally rendered target, remount the consumer with a key or34// switch to the callback-ref pattern (see use-hover). This fits targets that live as35// long as the component: window / document / an element always in the tree.36export function useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement = HTMLElement>(37 eventName: K,38 handler: (event: HTMLElementEventMap[K]) => void,39 options: UseEventListenerOptions & { target: TargetRef<T> },40): void4142/**43 * Typed event listening against three kinds of target — window (the default),44 * document, or any element ref — narrowing `eventName` / `handler` to the native45 * event map that matches.46 *47 * The core is the latest-ref for the handler: `handler` is synced into a ref after48 * every render, while the effect that actually calls `addEventListener` depends only49 * on `eventName` / `target` / the primitives pulled out of `options`50 * (`passive` / `capture`) — never on the `options` object, and never on `handler`.51 * So a consumer passing a freshly built `handler` on every render (closing over the52 * latest state, which is the common case) does not thrash the listener; when it53// … truncated
Files it writes
More from zyeon
All 893 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| useAsyncuse-async | zyeon | Hooks | Free | no deps | |
| useBatteryuse-battery | zyeon | Hooks | Free | no deps | |
| useBroadcastChanneluse-broadcast-channel | zyeon | Hooks | Free | no deps | |
| useClickOutsideuse-click-outside | zyeon | Hooks | Free | no deps | |
| useClipboardPasteuse-clipboard-paste | zyeon | Hooks | Free | no deps | |
| useControllableStateuse-controllable-state | zyeon | Hooks | Free | no deps | |
| useCookieuse-cookie | zyeon | Hooks | Free | no deps | |
| useCopyToClipboarduse-copy-to-clipboard | zyeon | Hooks | Free | no deps |
