Appearance
useClickOutside
Listen for clicks outside of an element. Useful for modals or dropdowns.
Demo
Usage
tsx
import { useClickOutside } from '@reause/core'
import { useRef } from 'react'
function App() {
const target = useRef<HTMLDivElement>(null)
useClickOutside(target, (event) => {
console.log(event)
})
return (
<div>
<div ref={target}>
Hello world
</div>
<div>Outside element</div>
</div>
)
}Return Value
useClickOutside returns a stop function to remove the event listeners.
tsx
const stop = useClickOutside(target, handler)
// Later, stop listening
stop()Controls
If you need more control over triggering the handler, you can use the controls option. This returns an object with stop, cancel, and trigger functions.
tsx
const { stop, cancel, trigger } = useClickOutside(
modalRef,
(event) => {
setModal(false)
},
{ controls: true },
)
// cancel prevents the next click from triggering the handler
cancel()
// trigger manually fires the handler
trigger(event)
// stop removes all event listeners
stop()As in upstream,
cancel()suppresses only the nextclickevent that reaches the handler: a physical mouse press re-evaluates the flag in thepointerdownlistener first, socancel()does not block a subsequent physical click.
Ignore Elements
Use the ignore option to prevent certain elements from triggering the handler. Provide elements as an array of refs or CSS selectors.
tsx
const ignoreElRef = useRef<HTMLDivElement>(null)
useClickOutside(
target,
event => console.log(event),
{ ignore: [ignoreElRef, '.ignore-class', '#ignore-id'] },
)Capture Phase
By default, the event listener uses the capture phase (capture: true). Set capture: false to use the bubbling phase instead.
tsx
useClickOutside(target, handler, { capture: false })Detect Iframe Clicks
Clicks inside an iframe are not detected by default. Enable detectIframe to also trigger the handler when focus moves to an iframe.
tsx
useClickOutside(target, handler, { detectIframe: true })Type Declarations
ts
export interface UseClickOutsideOptions<Controls extends boolean = false> extends ConfigurableWindow {
ignore?: (Element | string)[];
capture?: boolean;
detectIframe?: boolean;
controls?: Controls;
}
export type UseClickOutsideHandler = (event: PointerEvent | FocusEvent) => void
export interface UseClickOutsideControls {
stop: () => void;
cancel: () => void;
trigger: (event: Event) => void;
}
export type UseClickOutsideReturn<Controls extends boolean = false> = Controls extends true ? UseClickOutsideControls : () => void
export function useClickOutside<T extends UseClickOutsideOptions>(target: RefObject<Element | null | undefined>, handler: UseClickOutsideHandler, options?: T): () => void
export function useClickOutside(target: RefObject<Element | null | undefined>, handler: UseClickOutsideHandler, options: UseClickOutsideOptions<true>): UseClickOutsideControls