Detect click outside component using React Hooks

Hide Menu React Outside Click

Option A: Invisible full-screen box

You can do it by placing an invisible full-screen box. When the user clicks on the component, the full-screen invisible element appears on the background.

When the user clicks on the invisible element, the component hides.

jsx
<div className = 'Menu'>  
    <div onClick = {() => setShowMenu(false)} className = 'Invisible'></div>
        <ul>
            <li>Elem 1</li>
            <li>Elem 2</li>
            <li>Elem 3</li>
        </ul>
    </div>

Here is the CSS:

css
.Invisible{
  height: 100vh;
  left: 0;
  position: fixed;
  top: 0;
  width: 100vw;
  z-index: 0;
}

Here you can see the full code:

jsx
import React, { useState } from 'react';

const Menu = () =>{
    
    const [showMenu, setShowMenu] = useState(false);
  
    return (
        <div className = 'Nav'>
            <div onClick = {() => setShowMenu(true)} className = 'Click'>Dropdown menu</div>
            { showMenu      
            ? <div className = 'Menu'>  
                <div onClick = {() => setShowMenu(false)} className = 'Invisible'></div>
                    <ul>
                        <li>Elem 1</li>
                        <li>Elem 2</li>
                        <li>Elem 3</li>
                    </ul>
                </div>
            : null
            }
        </div>
    );
}

export default Menu;

Click here to play with it at CodePen.

Option B: useOutsideClick

You could create a useOutsideClick Hook to detect clicks outside the box. For example:

jsx
import { useEffect, useState } from 'react';

const useOutsideClick = (ref) => {
    
    const [clickOutside, setClickOutside] = useState(false);

    useEffect(() => {
      
        document.addEventListener('click', handleClick);
        
        return () => document.removeEventListener('click', handleClick);
      
    }, []);
    
    const handleClick = (e) => {
        
        ref.current?.contains(e.target)
        ? setClickOutside(false)
        : setClickOutside(true);   
        
    };
    
    return clickOutside;
    
};

export default useOutsideClick;

The component will be:

jsx
import React, { useState, useRef } from 'react';
import { useOutsideClick }         from './useOutsideClick';

const Menu = () => {
    
    const menuRef      = useRef();
    const outsideClick = useOutsideClick(menuRef);
  
    return (
        <div className = 'Nav'>
            <div className = 'Click' ref = {menuRef}>
                <div className = 'Title'>Dropdown menu</div>
                { !outsideClick 
                ? <div className = 'Menu'>  
                        <ul>
                            <li>Elem 1</li>
                            <li>Elem 2</li>
                            <li>Elem 3</li>
                        </ul>
                  </div>
                : null
                }
            </div>
        </div>
    );
}

export default Menu;

If the click occurs outside of div.Click, it will hide the menu items.

Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.