open-dropdown-menu-on-hover-react

How to open a dropdown menu on hover in React?

In this article, we are going to discuss a solution to open a dropdown menu on hover in react. A task was assigned to me recently to implement a solution to open a menu on button hover and close the menu when the mouse cursor is moved away from that button. I was looking for a pure react-based solution and not any other kind of solution. I found a react hook that would open a dropdown on the click event but didn’t find any that would work on hover, so I tweaked the “click event solution” a little bit and created this react hook that would work on mouseover and mouseout events.

Let’s create and use this hook to open a dropdown on hover

Create a sub-folder inside the src folder and name it “hooks” and then create a file – “src/hooks/useOnHoverOutside.js” and paste the below code in that.

import { useEffect } from "react";

export function useOnHoverOutside(ref, handler) {
  useEffect(
    () => {
      const listener = (event) => {
        if (!ref.current || ref.current.contains(event.target)) {
          return;
        }
        handler(event);
      };
      document.addEventListener("mouseover", listener);
      return () => {
        document.removeEventListener("mouseout", listener);
      };
    },
    [ref, handler]
  );
}

Now Create a menu component (src/components/menu.js) –

export default function Menu() {
    return (
        <>
            <div className="dropdown-menu">
                <a href>Item 1</a>
                <a href>Item 2</a>
                <a href>Item 3</a>
            </div>
        </>
    )
}

Create a header component (src/components/header.js) where we will utilize the useOnHoverOutside hook as well as the Menu component –

import logo from "./../logo.svg";
import { useState, useRef } from "react";
import { useOnHoverOutside } from "./../hooks/useOnHoverOutside";
import Menu from "./menu";

export function Header() {
  const dropdownRef = useRef(null); // Create a reference for dropdown container
  const [isMenuDropDownOpen, setMenuDropDownOpen] = useState(false);

  // Function to close dropdown
  const closeHoverMenu = () => {
    setMenuDropDownOpen(false);
  };

  useOnHoverOutside(dropdownRef, closeHoverMenu); // Call the hook

  return (
    <div class="flex justify-center header">
      <div class="container container-mobile flex justify-between laptop1280:py-[15px] py-[20px]">
        <div class="flex items-center">
          <a class="font-bold text-[30px]" href="/">
            <img src={logo} class="w-[80%]" alt="" />
          </a>
          <div class="ml-[62px] mobile:hidden" ref={dropdownRef}>
            <button
              class="text-dark-grey-100"
              onMouseOver={() => setMenuDropDownOpen(true)} //use mouseover event to show dropdown
            >
              Hover Menu
            </button>

            {isMenuDropDownOpen && <Menu />} // Dropdown
          </div>
        </div>
        <div class="flex items-center font-bold mobile:hidden">
          <a href class="mr-[50px] text-dark-green cursor-pointer">
            Login
          </a>
          <a
            href
            class="signup-button bg-green-500 text-white rounded-[30px] cursor-pointer"
          >
            Get Started Free
          </a>
        </div>
      </div>
    </div>
  );
}

Import this header component into the App component (src/App.js) –

import "./App.css";
import { Header } from "./components/header";

function App() {
  return (
    <div className="App">
      <Header />
    </div>
  );
}

export default App;

Here is the output of the above code

In the above output image, you can see that when we hover on Hover Menu, the menu appears and when we move the mouse away, the menu disappears. That is what we expected and that’s working in a pure react way. I hope this would help. Do let us know if you have other solutions.

Also read –
How to get the date range between the two dates using moment.js?
Javascript Interview Questions I was asked !!
How to split an array into equal chunks in javascript?

Leave a Comment