All hooks / Events and input

useClickOutside

187 B minified and brotliedSourceMarkdown✓ Works in all modern browsers

Calls handler when the user presses outside an element: mouse, touch, or pen. Returns a callback ref to put on the element.

Listens to pointerdown on the document, so it fires before focus moves and works for touch. Uses composedPath(), so presses inside shadow DOM count as inside.

Import

import { useClickOutside } from '@vincent.ri/react-tils'
// or only this hook
import { useClickOutside } from '@vincent.ri/react-tils/useClickOutside'

Usage

const [open, setOpen] = useState(false)
const ref = useClickOutside<HTMLDivElement>(() => setOpen(false), open)
// The ref wraps the button too, so pressing it toggles instead of closing and reopening.
return (
  <div ref={ref}>
    <button onClick={() => setOpen(!open)}>Menu</button>
    {open && <Menu />}
  </div>
)

Live demo

Open the menu, then click anywhere else.

When to use it

Closing a dropdown, popover, or menu when the user presses elsewhere.

When not to

You can use the native <dialog> or the popover attribute, which close on outside click and Escape with no JS. Content rendered in a portal is outside the element: put the ref on a wrapper that contains both, or ignore those targets in the handler. Put the ref on a wrapper around the toggle button too: if the button is outside, pressing it closes the menu and its click then reopens it.

API

function useClickOutside<T extends Element = HTMLElement>(handler: (event: PointerEvent) => void, enabled?: boolean): (element: T | null) => void
ParameterDescription
handlerCalled with the PointerEvent. Can change every render.
enabledListen only while true, e.g. while the menu is open. Default true.

Returns A callback ref. Pass it to the element's ref prop.

Browser support

UsesChromeEdgeFirefoxSafariChrome AndroidSafari iOS
Pointer eventsWidely available55+12+59+13+55+13+

First version with support, from MDN's compatibility data (web-features 3.42.0, @mdn/browser-compat-data 8.1.5).

Coming from another library?

Other libraries call this useClickAway, useOnClickOutside.