Click outside listener for React components in 10 lines of code [Using Hooks]

vibhanshu909

vibhanshu pandey

Posted on April 16, 2020

Click outside listener for React components in 10 lines of code [Using Hooks]

prerequisite: Please read my previous post to get an understanding of how one can implement a click outside listener in React in the first place, once you have an idea, this tutorial will become a lot simpler.

In the previous post, we learned how to implement a click outside listener without using any third-party libraries within just 10 lines of code.

In this tutorial, we will take a step further, and implement the same concept using our own custom hook, so let's begin.

Here's the hook:

// hooks/useClickOutsideListenerRef.tsx
import { useCallback, useEffect, useRef } from 'react'

export const useClickOutsideListenerRef = (onClose: () => void) => {
  const ref = useRef(null)
  const escapeListener = useCallback((e: KeyboardEvent) => {
    if (e.key === 'Escape') {
      onClose()
    }
  }, [])
  const clickListener = useCallback(
    (e: MouseEvent) => {
      if (!(ref.current! as any).contains(e.target)) {
        onClose?.()
      }
    },
    [ref.current],
  )
  useEffect(() => {
    document.addEventListener('click', clickListener)
    document.addEventListener('keyup', escapeListener)
    return () => {
      document.removeEventListener('click', clickListener)
      document.removeEventListener('keyup', escapeListener)
    }
  }, [])
  return ref
}
Enter fullscreen mode Exit fullscreen mode

Usage Example:

// components/Dialog.tsx
import React from 'react'
import { useClickOutsideListenerRef } from '../hooks/useClickoutsideListenerRef'

export interface IDialogProps {
  onClose: () => void
}

export const Dialog: React.FC<IDialogProps> = props => {
  const { onClose, children } = props
  const ref = useClickOutsideListenerRef(onClose)
  // I'm using tailwindcss for my css, you can use whatever you want.
  return (
    <div className='w-screen h-screen fixed inset-0 z-50 dialog-container'>
      <div className='flex h-full'>
        <div
          ref={ref}
          className='bg-white p-3 md:w-1/3 max-w-3/4 rounded overflow-auto'
        >
          {children}
        </div>
      </div>

      <style jsx={true}>{`
        .dialog-container {
          background-color: rgba(0, 0, 0, 0.25);
        }
      `}</style>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Explanation

The useClickOutsideListenerRef hook takes a function which is invoked when the user clicks outside your component, and returns a ref which you need to refer to your Content Element, meaning the element that you want to interact with, i.e in this example the actual dialog box. So basically whenever the user click's outside the refered div element, the onClose method is invoked and the dialog is closed, but when the user click's inside the refered div the dialog remains open and stays interactive.

Enjoy.

💖 💪 🙅 🚩
vibhanshu909
vibhanshu pandey

Posted on April 16, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related