This is a really simple and straightforward, but also a really useful custom hook. This custom React hook takes care of setting up the event listener on a component mount and removing the listener on component unmount.
addEventListener and removeEventListener
Let's take a look at the addEventListener
and removeEventListener
function definitions so we can see what parameters we need to pass to the custom hook in order to make it flexible for all use-cases.
target.addEventListener(type, listener[, options]);
target.removeEventListener(type, listener[, options]);
From the definitions, we can see that both functions use the following parameters: target
,type
, listener
and options
. Now that we've established the input parameters, we can go ahead and create our hook.
Custom hook
import { useEffect } from 'react';
const useEventListener = (target, type, listener, ...options) => {
React.useEffect(
() => {
target.addEventListener(type, listener, ...options);
return () => {
target.removeEventListener(type, listener, ...options);
};
},
[target, type, listener, options]
);
};
We use useEffect
React hook to take care of what is happening on component mount and unmount. If you want to know more about useEffect
hook, I've covered it in detail here:
React: useEffect explained with lifecycle methods
Adrian Bece for PROTOTYP ・ Aug 5 '19
This is how we initiate our hook in another component (for example, we are listening to window resize event).
useEventListener(window, 'resize', handleWindowResize);
This hook works well if we pass a document
or window
or object. If that's going to be the use case for our custom hook, then we can leave it as it is. However, if we intend to pass refs, this custom hook will need some small modifications in order to also work with refs.
Adding ref functionality
import { useEffect } from 'react';
const useEventListener = (target, type, listener, ...options) => {
React.useEffect(
() => {
const targetIsRef = target.hasOwnProperty("current");
const currentTarget = targetIsRef ? target.current : target;
if (currentTarget)
currentTarget.addEventListener(type, listener, ...options);
return () => {
if (currentTarget)
currentTarget.removeEventListener(type, listener, ...options);
};
},
[target, type, listener, options]
);
};
Inside the useEffect
hook, we are checking if the passed target is a ref or a window
or a document
element.
This is how we are initializing our hook (we can initialize as many listeners as we need in the same component):
// Window resize listener
useEventListener(window, 'resize', handleWindowResize);
// You can also pass refs
const elementRef = useRef(null);
useEventListener(elementRef, 'mousedown', handleElementClick);
Codepen example
Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.
Top comments (1)
why you call React.useEffect when you import {useEffect} from 'react' ?