JAVASCRIPT
Safely Manage Event Listeners with useEventListener Hook
A flexible React hook to abstract away the complexity of adding and removing event listeners, ensuring proper cleanup and preventing memory leaks.
import { useEffect, useRef } from 'react';
function useEventListener(eventType, handler, element = window) {
// Create a ref that stores handler
const savedHandler = useRef();
// Update ref.current value if handler changes.
// This allows our effect below to always get latest handler ...
// ... without us needing to pass it in effect's dependency array.
useEffect(() => {
savedHandler.current = handler;
}, [handler]);
useEffect(() => {
// Make sure element supports addEventListener
// On another note, window object is not available on SSR
const isSupported = element && element.addEventListener;
if (!isSupported) return;
// Create event listener that calls handler function stored in ref
const eventListener = (event) => savedHandler.current(event);
// Add event listener
element.addEventListener(eventType, eventListener);
// Remove event listener on cleanup
return () => {
element.removeEventListener(eventType, eventListener);
};
}, [eventType, element]); // Re-run if eventType or element changes
return null;
}
export default useEventListener;
// Example Usage:
// function MyComponent() {
// const handleScroll = () => {
// console.log('Window scrolled!', window.scrollY);
// };
// useEventListener('scroll', handleScroll);
// const myRef = useRef();
// const handleClick = () => {
// console.log('Element clicked!');
// };
// useEventListener('click', handleClick, myRef.current); // Attaching to a specific element
// return <div ref={myRef} style={{ height: '200px', overflow: 'scroll' }}>Scrollable Content</div>;
// }
How it works: The `useEventListener` hook simplifies the process of attaching and detaching event listeners to the `window`, `document`, or specific DOM elements. It ensures that listeners are properly cleaned up when the component unmounts or when the event type or target element changes, preventing memory leaks and making event management declarative in React.