JAVASCRIPT
Detecting Clicks Outside a Component with useClickOutside Hook
Create a useClickOutside React hook to handle UI interactions like closing modals, dropdowns, or tooltips when a user clicks anywhere outside a specific element.
import React, { useEffect, useRef } from 'react';
function useClickOutside(ref, handler) {
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]); // Only re-run if ref or handler changes
}
// Example usage:
function DropdownMenu() {
const [isOpen, setIsOpen] = React.useState(false);
const dropdownRef = useRef(null);
useClickOutside(dropdownRef, () => setIsOpen(false));
return (
<div ref={dropdownRef} style={{ position: 'relative', display: 'inline-block' }}>
<button onClick={() => setIsOpen(!isOpen)}>Toggle Dropdown</button>
{isOpen && (
<ul style={{ position: 'absolute', border: '1px solid gray', padding: '10px', backgroundColor: 'white' }}>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
)}
</div>
);
}
export default DropdownMenu;
How it works: The `useClickOutside` hook allows you to execute a function when a user clicks anywhere on the document *outside* of a specified React component. It takes a `ref` to the target component and a `handler` function. Inside a `useEffect` hook, it attaches `mousedown` and `touchstart` event listeners to the entire document. When an event occurs, it checks if the click originated inside the referenced element. If not, the provided handler is executed. This is extremely useful for dismissing popovers, menus, or modals when the user clicks away.