Create a Custom React Hook to Detect Outside Clicks
Managing dropdowns, modals, or other pop-up elements often requires detecting clicks outside these elements to close them.
Since it's a common problem, a clean and reusable solution is to create a custom React hook.
This article will guide you through creating a custom hook to detect outside clicks and touch events effectively.
How to
Create a new file useOutsideClick.js in your project with the following (don't worry I'll explain the code after):
import { useEffect, useRef } from 'react';
function useOutsideClick(callback) {
const ref = useRef();
useEffect(() => {
function handleClickOutside(event) {
if (ref.current && !ref.current.contains(event.target)) {
callback();
}
}
document.addEventListener('mousedown', handleClickOutside);
document.addEventListener('touchend', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
document.removeEventListener('touchend', handleClickOutside);
};
}, [callback]);
return ref;
}
export default useOutsideClick;
What doe this do?
- We use a
refto track the DOM element. - The
useEffecthook adds an event listener to detect clicks outside the referenced element. We listen tomousedownfor people on computers andtouchendfor touch screens. - The
handleClickOutsidefunction checks if the click is outside the element, triggering the callback if it is. - The cleanup function removes the event listener when the component unmounts.
Now, let's use this custom hook in a component, such as a dropdown menu:
import React, { useState } from 'react';
import useOutsideClick from './useOutsideClick';
function Dropdown() {
const [isOpen, setIsOpen] = useState(false);
const ref = useOutsideClick(() => setIsOpen(false));
return (
<div ref={ref} className="dropdown-container">
<button onClick={() => setIsOpen(!isOpen)}>Toggle Dropdown</button>
{isOpen && (
<div className="dropdown-menu">
<p>Dropdown Item 1</p>
<p>Dropdown Item 2</p>
<p>Dropdown Item 3</p>
</div>
)}
</div>
);
}
export default Dropdown;
In this component:
- We manage the dropdown's open state with
isOpenandsetIsOpen. - We use the
useOutsideClickhook, passing a callback to set the open state tofalseso that we auto-magically update our UI when we detect the outside click. ThereffromuseOutsideClickis attached to the dropdown's container element, which infers which element it is listening to.
