DEV Community

Cover image for Detecting click outside the scope in react
Hussain Md. Safwan
Hussain Md. Safwan

Posted on

Detecting click outside the scope in react

Detecting click outside a certain context is often needed to perform operations such as dismissing any floating components such as modals and dropdown drawers. In react, such flexibility can easily be achieved with a simple user-defined hook.

In this tutorial, there's a button that, when pressed, triggers a modal and we intend to dismiss the modal when a click occurs outside the scope.

The trick here is to define a custom hook, that takes in three parameters,

  • A ref that refers to the element to be acted upon, the modal in this case.
  • A callback function that illustrates the action to be carried out.
  • The state variable to be toggled.

While inside the hook, we wait for a click event to occur and when it does, it is to be checked if the click zone is contained within the scope of the given ref, if not, the callback function is called.
The skeleton might be like this,

const customHook = (ref, callback, state) => {
  document.listenFor('click', e => {
    if ( !ref.contains(e.target) && state ) {
      callback()
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

A working piece might however look like,

  const [open, setOpen] = useState(false)
  const modalRef = createRef(null)

  const useOutsideClick = (ref, callback, when) => {
    const savedCallback = useRef(callback)
    useEffect(() => {
      savedCallback.current = callback
    })
    const handler = e => {
      if (ref.current && !ref.current.contains(e.target)) {
        setOpen(false)
        savedCallback.current()
      }
    }
    useEffect(() => {
      if (when) {
          document.addEventListener('click', handler)
          return () => {document.removeEventListener('click', handler)}
      }
    }, [when])
  }

  useOutsideClick(modalRef, () => {setOpen(false)}, open)
Enter fullscreen mode Exit fullscreen mode

Here's a link to the sandbox.

Top comments (0)