'How to prevent the onmouseleave event from being triggered outside the browser?

I have a little try below. When i enter the mouse inside of the basket, a dropdown with a button appears. When we click the button a modal appears.I want the modal to close only when the close modal button is clicked. But when we take the mouse out of the browser the hideDropdown function is triggered and the modal closes. I sent the hideDropdown function as a prop to the component whose Modal state was updated, but this time only the hideDropdown function worked and the isModalShow state was not updated. How can i solve this?

Demo: https://codesandbox.io/s/jolly-buck-1lgmiu



Solution 1:[1]

This was tricky but i finally got it. You have to add the functions like below. The side effect is the open modal button will toggle sometime but that can be changed if you lift up the modal as it depends on the dropdown, I guess or implement simply using CSS instead which would be much easier.

But coming to your main question for onMouseleave you can do like following. This is basically checking the boundaries of the browser. Added 10 instead of 0 because the scrollbar was somehow messing with the event firing in codepen. So, added as a safeguard.

Also, used onMouseOver instead of onMouseEnter.

 const hideDropdown = (event) => {
    if (
      event.clientY <= 10 ||
      event.clientX <= 10 ||
      event.clientX >= window.innerWidth - 10 ||
      event.clientY >= window.innerHeight - 10
    ) {
      console.log("I'm out");
      return;
    } 
    setIsDropdownShow(false);
  };

  return (
    <div className="App" onMouseOver={showDropdown} onMouseLeave={hideDropdown}>
      <span className="basket">Basket</span>
      {isDropdownShow && <Dropdown hideDropdown={hideDropdown} />}
    </div>

Here is the sandbox link

Solution 2:[2]

Can you try to unlink the Modal from the isDropdownShow property so that it can be toggled only the button OpenModal and CloseModal... Just a workaround

import "./styles.css";
import Dropdown from "./Dropdown";
import { useState } from "react";

export default function App() {
  const [isDropdownShow, setIsDropdownShow] = useState(false);
  const [isModalShow, setIsModalShow] = useState(false);
  
  const showDropdown = () => {
    setIsDropdownShow(true);
  };

const showModal = () => {
    setIsModalShow(true);
  };
const hideModal = () => {
    setIsModalShow(false);
  };

  const hideDropdown = () => {
    setIsDropdownShow(false);
  };

  return (
    <div
      className="App"
      
    >
  <div
      onMouseEnter={showDropdown}
      onMouseLeave={hideDropdown}>
      <span 
      
      className="basket">Basket</span>
      {isDropdownShow && <button onClick={()=>showModal}> Open 
     Modal<button/>}
  </div>
      <Dropdown hideModal={hideModal} IsModalShow={IsModalShow} />
    </div>
  );
}

Solution 3:[3]

Basic solution would be checking if user in window or not with window. Here is the working codesandbox sample https://codesandbox.io/embed/heuristic-pasteur-u4cd5e?fontsize=14&hidenavigation=1&theme=dark

import "./styles.css";
import Dropdown from "./Dropdown";
import { useState } from "react";

export default function App() {
  const [isDropdownShow, setIsDropdownShow] = useState(false);

  const showDropdown = () => {
    setIsDropdownShow(true);
  };

  const hideDropdown = (event) => {
    if( typeof window !== "undefined" &&
         window.document &&
         window.document.createElement ){
      return;
    }
    setIsDropdownShow(false);
  };

  return (
    <div
      className="App"
      onMouseEnter={showDropdown}
      onMouseLeave={hideDropdown}
    >
      <span className="basket">Basket</span>
      {isDropdownShow && <Dropdown hideDropdown={hideDropdown} />}
    </div>
  );
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 innocent
Solution 2
Solution 3 Evren