Skip to main content

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;
ParameterTypeDescription
refRefObject<HTMLElement>Ref of the element to detect outside clicks against.
callback() => voidInvoked when a click/touch occurs outside the element.

Returns: void

Usage notes​

  • Listens for both click and touchstart events, 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

use-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]);
};