useEventListener()
Last updated: 24/04/2026
Overview
useEventListener subscribes addEventListener on a target (default window if omitted) and removes the listener on unmount or when eventName or target change. The latest listener is kept in a ref so you do not rebind on every render while still seeing fresh closures. target can be a DOM node, window, document, MediaQueryList, or a ref whose .current is used; the effect depends on the ref object, not .current, so re-pointing a ref to a new element may require a key or a dedicated effect. Event names are typed from WindowEventMap in TypeScript. The hook returns nothing-it is a side-effect utility.
What it accepts
eventName- A key ofWindowEventMap(e.g.resize,keydown)listener- Handler receiving the typed event- Optional
target- Event target, or a ref; defaults towindow
What it returns
void
Usage
Track inner viewport width on window resize.
import { useState } from 'react'
import useEventListener from '@dedalik/use-react/useEventListener'
function Example() {
const [width, setWidth] = useState(typeof window === 'undefined' ? 0 : window.innerWidth)
useEventListener('resize', () => {
setWidth(window.innerWidth)
})
return (
<p>
Window inner width: <strong>{width}</strong> px
</p>
)
}
export default function Demo() {
return <Example />
}API Reference
useEventListener
Signature: useEventListener<KW extends keyof WindowEventMap>(eventName: KW, listener: (event: WindowEventMap[KW]) => void, target?: Target | RefObject<Target>): void
Parameters
eventNamelistenertarget(optional)
Returns
void
Copy-paste hook
TypeScript
import { RefObject, useEffect, useRef } from 'react'
type Target = Window | Document | HTMLElement | MediaQueryList | null
export default function useEventListener<KW extends keyof WindowEventMap>(
eventName: KW,
listener: (event: WindowEventMap[KW]) => void,
target?: Target | RefObject<Target>,
) {
const savedListener = useRef(listener)
useEffect(() => {
savedListener.current = listener
}, [listener])
useEffect(() => {
const targetValue =
target && 'current' in target ? target.current : target || (typeof window !== 'undefined' ? window : null)
if (!targetValue?.addEventListener) {
return
}
const eventListener = (event: Event) => savedListener.current(event as WindowEventMap[KW])
targetValue.addEventListener(eventName, eventListener as EventListener)
return () => targetValue.removeEventListener(eventName, eventListener as EventListener)
}, [eventName, target])
}JavaScript
import { useEffect, useRef } from 'react'
export default function useEventListener(eventName, listener, target) {
const savedListener = useRef(listener)
useEffect(() => {
savedListener.current = listener
}, [listener])
useEffect(() => {
const targetValue =
target && 'current' in target ? target.current : target || (typeof window !== 'undefined' ? window : null)
if (!targetValue?.addEventListener) {
return
}
const eventListener = (event) => savedListener.current(event)
targetValue.addEventListener(eventName, eventListener)
return () => targetValue.removeEventListener(eventName, eventListener)
}, [eventName, target])
}