Skip to main content

Overview

The useClickOutside hook listens for mouse and touch events outside a specified element and executes a callback function when such events occur. This is commonly used for closing dropdowns, modals, or other UI elements when users click outside of them.

Function Signature

const useClickOutside = <T extends HTMLElement = HTMLElement>(
  ref: RefObject<T>,
  callback: () => void
) => void

Parameters

ref
RefObject<T>
required
A React ref object pointing to the HTML element you want to monitor. The hook will detect clicks outside this element.
callback
() => void
required
A function that will be called when a click or touch event occurs outside the referenced element.

Return Value

This hook does not return any value. It only sets up event listeners and executes the provided callback when appropriate.

Usage Example

Here’s a real-world example from the BookmarkTags component (/home/daytona/workspace/source/src/components/BookmarkTags.tsx:60):
import { useRef } from "react"
import useClickOutside from "../hooks/useClickOutside"

const BookmarkTags = ({ bookmark }) => {
  const tagListRef = useRef<HTMLDivElement>(null)
  const [editable, setEditable] = useState(false)
  const [inputValue, setInputValue] = useState("")
  const [newTags, setNewTags] = useState(bookmark.tags)

  // Close the tag editor when clicking outside
  useClickOutside(tagListRef, () => { 
    setEditable(false)
    setInputValue("")
    setNewTags(bookmark.tags)
  })

  return (
    <div ref={tagListRef} onClick={() => setEditable(true)}>
      {/* Tag editing UI */}
    </div>
  )
}

Implementation Details

The hook:
  • Listens for both mousedown and touchstart events on the document
  • Checks if the event target is outside the referenced element using Node.contains()
  • Automatically cleans up event listeners when the component unmounts
  • Re-attaches listeners when the ref or callback changes

Common Use Cases

  • Closing dropdown menus when clicking outside
  • Dismissing modals or popovers
  • Exiting edit mode in inline editors
  • Hiding tooltips or context menus

Notes

The callback function should be memoized using useCallback if it depends on component state to prevent unnecessary re-renders and listener re-attachments.
Make sure the ref is properly attached to a DOM element before the hook runs, otherwise the click detection will not work correctly.

Build docs developers (and LLMs) love