useEventListener
A React hook for managing DOM event listeners with proper cleanup.
Installation
Props
Prop | Type | Default | Description |
---|---|---|---|
eventName | keyof WindowEventMap | Required | The DOM event name to listen for |
handler | (event: Event) => void | Required | The callback function for the event |
element | RefObject<HTMLElement> | EventTarget | window | The element to attach the listener to |
options | boolean | AddEventListenerOptions | undefined | Options for addEventListener |
Data
The hook does not return any data.
Key Features & Details
useEventListener
provides a clean, type-safe way to manage DOM event listeners in React components with these benefits:
- Automatically handles cleanup on unmount to prevent memory leaks
- Preserves handler reference between renders with a ref
- Type-safe event names and handler parameters
- Works with window, document, or specific DOM elements
- Supports all AddEventListener options
Browser Support
This hook relies on the standard DOM addEventListener API, which is supported in all modern browsers:
- Chrome: Full support
- Firefox: Full support
- Safari: Full support
- Edge: Full support
- Opera: Full support
Performance Considerations
- Uses
useRef
to avoid recreating event listeners on each render - Minimizes re-renders by not returning state
- Automatic cleanup prevents memory leaks
- Minimal overhead compared to direct event listeners
Best Practices & Caveats
- Always provide a stable handler or use useCallback for the event handler
- For element refs, ensure the element is mounted before the hook runs
- For high-frequency events like mousemove or scroll, consider debouncing or throttling
- TypeScript users benefit from complete type safety for events
- Be cautious with passive events on touch devices for performance
Examples
Basic Usage with Window
import { useEventListener } from '@/hooks/use-event-listener';
function WindowSize() {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEventListener({
eventName: 'resize',
handler: () => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
},
});
return (
<div>
Window Size: {windowSize.width} x {windowSize.height}
</div>
);
}
Using with Element Refs
import { useRef } from 'react';
import { useEventListener } from '@/hooks/use-event-listener';
function ClickCounter() {
const [count, setCount] = useState(0);
const buttonRef = useRef(null);
useEventListener({
eventName: 'click',
handler: () => setCount((prev) => prev + 1),
element: buttonRef,
});
return <button ref={buttonRef}>Clicked {count} times</button>;
}
With Event Options
import { useEventListener } from '@/hooks/use-event-listener';
function ScrollHandler() {
useEventListener({
eventName: 'scroll',
handler: (e) => {
console.log('Scroll event with passive option');
},
options: { passive: true },
});
return <div>Scroll the page</div>;
}