useOnClickOutside()

React hook for listening for clicks outside of a specified element (see useRef).

This can be useful for closing a modal, a dropdown menu etc.

The Hook

1import { RefObject, useEffect } from 'react'
2
3type AnyEvent = MouseEvent | TouchEvent
4
5function useOnClickOutside<T extends HTMLElement = HTMLElement>(
6 ref: RefObject<T>,
7 handler: (event: AnyEvent) => void,
8) {
9 useEffect(() => {
10 const listener = (event: AnyEvent) => {
11 const el = ref?.current
12
13 // Do nothing if clicking ref's element or descendent elements
14 if (!el || el.contains(event.target as Node)) {
15 return
16 }
17
18 handler(event)
19 }
20
21 document.addEventListener(`mousedown`, listener)
22 document.addEventListener(`touchstart`, listener)
23
24 return () => {
25 document.removeEventListener(`mousedown`, listener)
26 document.removeEventListener(`touchstart`, listener)
27 }
28
29 // Reload only if ref or handler changes
30 }, [ref, handler])
31}
32
33export default useOnClickOutside

Usage

1import React, { useRef } from 'react'
2
3import useOnClickOutside from './useOnClickOutside'
4
5export default function Component() {
6 const ref = useRef(null)
7
8 const handleClickOutside = () => {
9 // Your custom logic here
10 console.log('clicked outside')
11 }
12
13 const handleClickInside = () => {
14 // Your custom logic here
15 console.log('clicked inside')
16 }
17
18 useOnClickOutside(ref, handleClickOutside)
19
20 return (
21 <div
22 ref={ref}
23 onClick={handleClickInside}
24 style={{ width: 200, height: 200, background: 'cyan' }}
25 />
26 )
27}

Created:
about 1 year ago