useEventListener
If you find yourself adding a lot of event listeners using useEffect
you might consider moving that logic to a custom hook. In the recipe below we create a useEventListener
hook that handles checking if addEventListener
is supported, adding the event listener, and removal on cleanup.
Usage
import { useRef, useEffect, RefObject } from 'react';
type EventHandler<T extends Event> = (event: T) => void;
const useEventListener = <T extends Event>(
eventName: string,
handler: EventHandler<T>,
element: RefObject<Element> = document
) => {
const savedHandler = useRef<EventHandler<T>>();
useEffect(() => {
savedHandler.current = handler;
}, [handler]);
useEffect(() => {
const isSupported = element.current && element.current.addEventListener;
if (!isSupported) return;
const eventListener: EventHandler<T> = (event: T) => savedHandler.current?.(event);
element.current.addEventListener(eventName, eventListener);
return () => {
element.current.removeEventListener(eventName, eventListener);
};
}, [eventName, element]);
};
export default useEventListener;
Here's how you can use the useEventListener
hook in a React component:
import { useRef } from 'react';
import useEventListener from './useEventListener';
const ExampleComponent = () => {
const elementRef = useRef<HTMLDivElement>(null);
const handleClick = () => {
console.log('Element clicked!');
};
useEventListener('click', handleClick, elementRef);
return (
<div ref={elementRef}>
<p>Click me!</p>
</div>
);
};
export default ExampleComponent;
In this example, the useEventListener
hook takes three arguments: the name of the event to listen for, a function to handle the event, and an optional RefObject
that refers to the element on which to listen for the event (defaulting to document
). The ExampleComponent
uses this hook to listen for clicks on a <div>
element and log a message when clicked.
Last updated