DEV Community

Cover image for React Custom Hook: useClickOutside
Sergey Leschev
Sergey Leschev

Posted on

React Custom Hook: useClickOutside

In this article series, we embark on a journey through the realm of custom React hooks, discovering their immense potential for elevating your development projects. Our focus today is on the "useClickOutside" hook, one of the many carefully crafted hooks available in the collection of React custom hooks.

Github: https://github.com/sergeyleschev/react-custom-hooks

import useEventListener from "../useEventListener/useEventListener"

export default function useClickOutside(ref, cb) {
    useEventListener("click", e => {
        if (ref.current == null || ref.current.contains(e.target)) return
        cb(e)
    }, document)
}
Enter fullscreen mode Exit fullscreen mode

The useClickOutside hook is designed to simplify the process of detecting clicks outside a specified component. By utilizing the useEventListener hook, it listens for click events on the document level, allowing you to trigger a callback function when a click occurs outside the provided component's reference.

One of the main advantages of useClickOutside is its ease of use. Simply import the hook into your component and pass the desired component's reference and a callback function. The hook takes care of the event listener setup and cleanup, saving you time and effort. Plus, it works seamlessly with functional components using the useState and useRef hooks.

The potential applications for useClickOutside are endless. It is particularly useful when implementing modal windows, dropdown menus, or any element that should be closed when a user interacts with anything outside of it. By incorporating useClickOutside, you can enhance the user experience by providing intuitive and efficient interactions.

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

export default function ClickOutsideComponent() {
    const [open, setOpen] = useState(false)
    const modalRef = useRef()

    useClickOutside(modalRef, () => {
        if (open) setOpen(false)
    })

    return (
        <>
            <button onClick={() => setOpen(true)}>Open</button>
            <div
                ref={modalRef}
                style={{
                    display: open ? "block" : "none",
                    backgroundColor: "blue",
                    color: "white",
                    width: "100px",
                    height: "100px",
                    position: "absolute",
                    top: "calc(50% - 50px)",
                    left: "calc(50% - 50px)",
                }}
            >
                <span>Modal</span>
            </div>
        </>
    )
}
Enter fullscreen mode Exit fullscreen mode

To see useClickOutside in action, take a look at the example above. In this case, the ClickOutsideComponent utilizes the hook to toggle the visibility of a modal window. When the user clicks outside the modal, the provided callback function sets the open state to false, closing the modal. This way, the component offers a sleek and user-friendly way to manage the modal's visibility.

Full Version | React Custom Hooks:
https://dev.to/sergeyleschev/supercharge-your-react-projects-with-custom-hooks-pl4

Top comments (4)

Collapse
 
elsyng profile image
Ellis • Edited

Just wanted to point out a "more html" alternative to this "more js" solution, which I use because I personally find simpler:

With a typical modal, we can typically have 3 layers:

  1. z-index 0 or none: your app,
  2. z-index 1: the semi-transparent gray backdrop for the modal,
  3. z-index 2: the modal.

The solution is just to use: backdrop.onClick --> anything you want to do on clicking outside.

Collapse
 
sergeyleschev profile image
Sergey Leschev

Ellis, thanks for sharing your alternative approach! Your suggestion of utilizing z-index layers and handling the click event on the backdrop is indeed a simpler way to achieve the same outcome. Different approaches can suit different preferences and project requirements. It's great to have multiple options for solving common challenges.

Collapse
 
overflow profile image
overFlow

I really seen I think that you are good with just Vanilla-as in algorithms and stuff. but I see you seem to like React a lot

Collapse
 
sergeyleschev profile image
Sergey Leschev

I'm also passionate about React because of its power to streamline UI development.