useOutsideClick
Invokes a callback whenever a click or touch event occurs outside a given element. Ideal for closing dropdowns, modals, or popovers automatically.
When to use it
- Closing a dropdown menu when the user clicks elsewhere on the page.
- Dismissing a modal or tooltip on an outside click/tap.
- Any UI that should collapse when focus moves away from it.
Demo
Open the dropdown, then click anywhere outside of it to close it.
Loading demo…
Signature
function useOutsideClick(
ref: RefObject<HTMLElement>,
callback: () => void
): void;
| Parameter | Type | Description |
|---|---|---|
ref | RefObject<HTMLElement> | Ref of the element to detect outside clicks against. |
callback | () => void | Invoked when a click/touch occurs outside the element. |
Returns: void
Usage notes
- Listens for both
clickandtouchstartevents, so it works well on touch devices too. - Automatically removes its event listeners on unmount.
- The callback fires only when the event target is outside the referenced element (clicks inside it are ignored).
Hook source
View useOutsideClick source
useOutsideClick sourceuse-outside-click.ts
import type { RefObject } from "react";
import { useEffect } from "react";
/**
* A custom React hook that triggers a callback function when a click or touch event occurs outside the specified element.
*
* This hook is useful for handling scenarios like closing dropdowns, modals, or tooltips when clicking outside the component.
*
* @param {RefObject<HTMLElement>} ref - A React ref object pointing to the element to detect outside clicks for.
* @param {() => void} callback - The callback function to execute when a click or touch event occurs outside the specified element.
*
* @example
* ```typescript
* const ref = useRef<HTMLDivElement>(null);
* useOutsideClick(ref, () => {
* console.log("Clicked outside the component");
* });
*
* return <div ref={ref}>Click outside this element</div>;
* ```
*
* For a live, editable example, see the [useOutsideClick docs page](https://altalyst-solutions.github.io/hookify/hooks/use-outside-click).
*/
export const useOutsideClick = (
ref: RefObject<HTMLElement>,
callback: () => void
) => {
useEffect(() => {
const handleOutsideClick = (event: MouseEvent | TouchEvent) => {
if (ref.current && !ref.current.contains(event.target as Node)) {
callback();
}
};
document.addEventListener("click", handleOutsideClick);
document.addEventListener("touchstart", handleOutsideClick);
return () => {
document.removeEventListener("click", handleOutsideClick);
document.removeEventListener("touchstart", handleOutsideClick);
};
}, [ref, callback]);
};