How to Detect a Click Outside of a React Component

Detect click outside React
Table of Contents

Detecting clicks outside a React component enhances user interactions by managing behaviors like closing tooltip, modals, or dropdown component when users click outside them. This technique ensures a more polished and user-friendly interface in your React app.

Why Detect Clicks Outside?

  1. Improved Usability: When clicking elsewhere, elements like dropdowns automatically close, ensuring that the interface remains clean and user-friendly.
  2. Enhanced User Experience: Prevents interface clutter and enhances interaction by ensuring that only the necessary elements are visible at any time.

Creating the Hook

To detect clicks outside a component in React, you can use the useEffect hook for functional components. Here’s a custom React click outside hook to handle clicks outside of a component. This approach ensures that your React component can respond appropriately when a click event occurs outside its boundaries.

import { RefObject, useEffect } from 'react'

export const useClickOutside = (
  ref: RefObject<HTMLElement | undefined>,
  callback: () => void
) => {
  const handleClick = (event: MouseEvent) => {
    if (ref.current && !ref.current.contains(event.target as HTMLElement)) {
      callback()
    }
  }

  useEffect(() => {
    document.addEventListener('click', handleClick)

    return () => {
      document.removeEventListener('click', handleClick)
    }
  })
}

Conditional Event Listener

In scenarios where the event listener should be added conditionally, for example, only when the component is visible. You can use the following implementation:

import { RefObject, useEffect } from 'react'

export const useClickOutside = (
  ref: RefObject<HTMLElement | undefined>,
  callback: () => void,
  addEventListener = true,
) => {
  const handleClick = (event: MouseEvent) => {
    if (ref.current && !ref.current.contains(event.target as HTMLElement)) {
      callback()
    }
  }

  useEffect(() => {
    if (addEventListener) {
      document.addEventListener('click', handleClick)
    }

    return () => {
      document.removeEventListener('click', handleClick)
    }
  })
}

We utilize this solution in dropdowns where the menu is hidden by default.

Explanation of the Hook

Parameters:

  • ref: A reference to the specific component to detect outside clicks.
  • callback: Function to call when an outside click is detected.
  • addEventListener: Boolean to control adding/removing the event listener.

Logic:

  • Adds a click event listener when the component mounts.
  • Removes the event listener when the component unmounts or addEventListener is false.
  • If the click event occurs outside the referenced element, the callback function is invoked.

Using the Hook in a React Components

Integrate the useClickOutside hook in your functional component to manage click events effectively.

import { useRef, useState } from 'react'
import { useClickOutside } from './useClickOutside'

export const Dialog = ({ onClickOutside, show, text }) => {
  const ref = useRef<HTMLDivElement>(null)
  useClickOutside(ref, onClickOutside)

  return show && (
    <div ref={ref} className="dialog-component">
      {text}
    </div>
  )
}

Here’s how to use the Dialog component in your React app, demonstrating the practical application of outside click detection.

import { useState } from 'react'
import Dialog from './Dialog'

const App = () => {
  const [showDialog, setShowDialog] = useState(false)

  return (
    <div>
      <button onClick={() => setShowDialog(true)}>Show Dialog</button>
      <Dialog
        show={showDialog}
        onClickOutside={() => setShowDialog(false)}
        text="Click outside to close this"
      />
    </div>
  )
}

export default App

Handling Complex Scenarios

For more complex scenarios, like nested components, ensure the useClickOutside hook logic accommodates the specific requirements. This might involve checking multiple references or managing state more intricately to ensure accurate click detection.

Benefits of Custom Hook

  1. Reusability: The hook can be reused across different components, making it a versatile solution.
  2. Encapsulation: Keeps the logic of detecting outside clicks encapsulated within a hook, promoting cleaner and more maintainable code.
  3. Simplicity: Simplifies the component code, allowing developers to focus on rendering logic rather than event handling.

Conclusion

Detecting clicks outside a component in React is essential for creating interactive and user-friendly interfaces. Using a custom hook like useClickOutside helps maintain clean and reusable code. This approach enhances user experience by managing component visibility based on user interactions efficiently.

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.