JAVASCRIPT
Handling Clicks Outside a Component with useOnClickOutside
Implement a `useOnClickOutside` React hook to detect clicks outside a specified element, perfect for closing dropdowns, modals, or context menus.
function useOnClickOutside(ref, handler) {
React.useEffect(() => {
const listener = (event) => {
// Do nothing if clicking ref's element or descendant elements
if (!ref.current || ref.current.contains(event.target)) {
return;
}
handler(event);
};
document.addEventListener('mousedown', listener);
document.addEventListener('touchstart', listener);
return () => {
document.removeEventListener('mousedown', listener);
document.removeEventListener('touchstart', listener);
};
}, [ref, handler]); // Re-run if ref or handler changes
}
// Example usage:
function Dropdown() {
const [isOpen, setIsOpen] = React.useState(false);
const dropdownRef = React.useRef();
useOnClickOutside(dropdownRef, () => setIsOpen(false));
return (
React.createElement("div", { ref: dropdownRef, style: { position: 'relative', display: 'inline-block' } },
React.createElement("button", { onClick: () => setIsOpen(!isOpen) }, "Toggle Dropdown"),
isOpen && (
React.createElement("div", {
style: {
position: 'absolute', top: '100%', left: 0,
border: '1px solid #ccc', padding: '10px', background: 'white'
}
},
"Dropdown Content"
)
)
)
);
}
How it works: The `useOnClickOutside` hook simplifies the common pattern of closing a UI element (like a dropdown or modal) when a user clicks outside of it. It takes a `ref` to the element and a `handler` function. Internally, it attaches `mousedown` and `touchstart` event listeners to the document. When an event occurs, it checks if the click originated from inside the referenced element or its children. If not, it executes the provided `handler`. The `useEffect` hook ensures the listeners are properly attached and cleaned up when the component mounts/unmounts or dependencies change.