use-outside-click
A React hook that detects outside click for specified element and triggers the given callback.
TIP
Perfect for implementing modals, dropdowns and other UI components that need to be closed when users click outside of them.
Features
- Precise trigger: Precise outside click detection
- Performance: Optimized with capture phase events
- Underlying hook: At its core, it uses useEventListener hook
Parameters
Parameter | Type | Required | Default Value | Description |
---|---|---|---|---|
target | EvTarget | ✅ | - | Function that returns the target element or null |
handler | EvHandler | ❌ | undefined | Callback executed on outside click |
options | EvOptions | ❌ | undefined | Event listener options and feature flags |
Standard AddEventListenerOptions
Property | Type | Default | Description |
---|---|---|---|
capture | boolean | false | If true , the listener will be triggered during the capture phase |
once | boolean | false | If true , the listener will be automatically removed after being triggered once |
passive | boolean | false | If true , indicates that the function will never call preventDefault() |
signal | AbortSignal | undefined | An AbortSignal that can be used to remove the event listener |
Custom Options
Property | Type | Default | Description |
---|---|---|---|
shouldInjectEvent | boolean | any | true | Controls whether the event listener should be attached. When false, the event listener is not added |
Type Definitions
Details
tsx
type EvTarget = () => EventTarget | null
type EvHandler = (event: DocumentEventMap['click']) => void
interface EvOptions extends AddEventListenerOptions {
// Standard AddEventListenerOptions:
capture?: boolean
once?: boolean
passive?: boolean
signal?: AbortSignal
// Custom option:
shouldInjectEvent?: boolean | any // Controls whether the event should be attached
}
Return Value(s)
This hook does not return anything.
Common Use Cases
- Modal dialogs - Close when clicking backdrop
- Dropdown menus - Hide when clicking elsewhere
- Context menus - Dismiss on outside click
Usage Examples
Modal Component
ts
import { useRef, useState } from 'react'
import { useOutsideClick } from 'classic-react-hooks'
function Modal() {
const [isOpen, setIsOpen] = useState(false)
const modalRef = useRef<HTMLDivElement>(null)
useOutsideClick({
target: () => modalRef.current,
handler: () => setIsOpen(false),
})
if (!isOpen) {
return <button onClick={() => setIsOpen(true)}>Open Modal</button>
}
return (
<div className='modal-overlay'>
<div ref={modalRef} class='modal-content bg-white p-8 rounded-lg shadow-md'>
<h2>Modal Title</h2>
<p>Click outside this modal to close it.</p>
<button onClick={() => setIsOpen(false)}>Close</button>
</div>
</div>
)
}
Conditional Outside Click
Example
ts
function ConditionalOutsideClick() {
const [isModalOpen, setIsModalOpen] = useState(false)
const [isPinned, setIsPinned] = useState(false)
const modalRef = useRef<HTMLDivElement>(null)
useOutsideClick({
target: () => modalRef.current,
handler: () => {
// Only close if not pinned
if (!isPinned) {
setIsModalOpen(false)
}
},
})
return (
<div>
{isModalOpen && (
<div ref={modalRef}>
<button onClick={() => setIsPinned(!isPinned)}>{isPinned ? 'Unpin' : 'Pin'} Modal</button>
<p>Modal content</p>
</div>
)}
</div>
)
}
Dynamic Target
Example
ts
function DynamicTarget() {
const [activeElement, setActiveElement] = useState<HTMLElement | null>(null)
useOutsideClick({
target: () => activeElement,
handler: () => {
console.log('Clicked outside active element')
setActiveElement(null)
},
})
const makeActive = (element: HTMLElement) => {
setActiveElement(element)
}
return (
<div>
<div onClick={(e) => makeActive(e.currentTarget)} className='p-5 bg-gray-100 m-2.5'>
Click to make active
</div>
</div>
)
}