useClickAnywhereLoading saved progress…

useClickAnywhere

Build a hook that runs a callback whenever the user clicks anywhere on the page. A surprising number of features need this: closing a dropdown or popover on an outside click, dismissing a tooltip, tracking the last interaction time, or hiding a custom context menu. useClickAnywhere(handler) attaches a single click listener on window — which sees every click in the document because clicks bubble up to it — calls handler(event) each time, and removes the listener when the component unmounts.

Signature

function useClickAnywhere(
  handler: (event: MouseEvent) => void,
): void;

The hook returns nothing. It is a pre-bound cousin of useEventListener: the event is always click and the target is always window, so the only argument is the callback.

Examples

function ClickCounter() {
  const [clicks, setClicks] = useState(0);

  // Count every click anywhere on the page. Cleanup is automatic.
  useClickAnywhere(() => setClicks((c) => c + 1));

  return <span>Clicks: {clicks}</span>;
}
// Close an open menu when the user clicks anywhere:
useClickAnywhere((event) => {
  if (isOpen) setOpen(false);
});

Notes

  • Always window, always click. Unlike a general listener hook, the target and event are fixed. You only pass the callback.
  • The handler must never go stale. If the component re-renders with a new callback (inline arrow functions are recreated every render), the next click must call the new one — without re-subscribing.
  • Clean up on unmount. The listener must be removed when the component unmounts, or it leaks and keeps firing into a component that no longer exists.
  • The event is passed through. handler receives the MouseEvent, so callers can read event.target, coordinates, or modifier keys.
  • One subscription. Re-rendering with a new handler should not detach and re-attach the listener; the subscription stays put for the component's whole life.
Loading editor…