JAVASCRIPT
Custom `useClickOutside` Hook for Closing Modals/Dropdowns
Implement a React `useClickOutside` hook to detect clicks outside a specified DOM element, perfect for automatically closing dropdowns, modals, or context menus.
import { useEffect, useRef } from 'react';
function useClickOutside(handler) {
const domNodeRef = useRef();
useEffect(() => {
const maybeHandler = (event) => {
// If the clicked target is not within the ref's current element
if (domNodeRef.current && !domNodeRef.current.contains(event.target)) {
handler(); // Execute the provided handler function
}
};
document.addEventListener('mousedown', maybeHandler);
return () => {
document.removeEventListener('mousedown', maybeHandler);
};
}, [handler]); // Re-run effect if handler changes
return domNodeRef;
}
// Example Usage:
// function Dropdown() {
// const [isOpen, setIsOpen] = useState(false);
// const dropdownRef = useClickOutside(() => setIsOpen(false));
// return (
// <div ref={dropdownRef} style={{ border: '1px solid black', padding: '10px' }}>
// <button onClick={() => setIsOpen(!isOpen)}>Toggle Dropdown</button>
// {isOpen && (
// <ul style={{ background: '#f0f0f0', marginTop: '5px', listStyle: 'none', padding: '10px' }}>
// <li>Item 1</li>
// <li>Item 2</li>
// </ul>
// )}
// </div>
// );
// }
How it works: The `useClickOutside` hook takes a `handler` function as an argument and returns a `ref`. When a component mounts, it adds a `mousedown` event listener to the `document`. This listener checks if the clicked target is outside the element referenced by `domNodeRef`. If it is, the provided `handler` function is executed, typically to close a modal or dropdown. The `useEffect` cleanup function ensures the event listener is removed when the component unmounts, preventing memory leaks.