Skip to content

useClickOutside

Click outside element and run a callback, very helpful for element like dropdown

Rizki Maulana Citra

Created by / Rizki Maulana Citra

JS
export default function useClickOutside(refObject, handler) {
  useEffect(() => {
    const listener = (event) => {
      const element = refObject?.current
      if (!element || element.contains(event.target)) return
      handler(event)
    }

    // use mousedown or touchstart instead of click event
    document.addEventListener('mousedown', listener)
    document.addEventListener('touchstart', listener)

    /* upon unmounting, removes the event listeners. */
    return () => {
      document.removeEventListener('mousedown', listener)
      document.removeEventListener('touchstart', listener)
    }
  }, [refObject, handler])
}

TypeScript Implementation

TS
type Handler = (e: Event) => void

export const useClickOutside = <T extends HTMLElement = HTMLElement>(
  refObject: React.RefObject<T>,
  handler: Handler
) => {
  useEffect(() => {
    const listener = (e: Event) => {
      const el = refObject?.current
      if (!el || el.contains(e.target as Node)) {
        return
      }

      handler(e)
    }

    // use mousedown or touchstart instead of click event
    document.addEventListener('mousedown', listener)
    document.addEventListener('touchstart', listener)
    /* upon unmounting, removes the event listeners. */
    return () => {
      document.removeEventListener('mousedown', listener)
      document.removeEventListener('touchstart', listener)
    }
  }, [handler, refObject])
}