clearTimeout 一个函数中的计时器与另一个函数(React.js)

问题描述 投票:0回答:1

该代码适用于

Navbar
。我希望当鼠标离开它时,这个计时器就启动了,但是当我将鼠标移到
Navbar
上时,计时器计数将停止并更改为显示为“不应用”。问题是当我将鼠标移出
Navbar
然后再次移到它上面时,计时器不会停止,并且在计数结束时下拉显示消失了。

这是我的代码:

const [navOver, setNavOver] = useState(false);
const [currentItem, setCurrentItem] = useState("");

let timer;

const handleMouseOver = (item) => {
  setNavOver(true);
  clearTimeout(timer);
  for (var i = 0; i < dropdown.length; i += 1) {
    if (dropdown[i].style.display === "none") {
      dropdown[i].style.display = "block";
    }
  }
  if (!currentItem) {
    setCurrentItem(item);
  }
};

const handleMouseOut = (event) => {
  if (!event.relatedTarget || !event.relatedTarget.closest("nav")) {
    setNavOver(false);
    timer = setTimeout(() => {
      for (var i = 0; i < dropdown.length; i += 1) {
        dropdown[i].style.display = "none";
      }
    }, 700);
  }
};

和 jsx 代码:

<nav onMouseOut={handleMouseOut}>
  <ul className="lg:flex hidden gap-4 ps-4">
    {navLinks.map((item, index) => {
      return (
        <>
          <li key={index} className="z-50">
            <Link
              to={item.href}
              onMouseOver={() => {
                handleMouseOver(item);
                setCurrentItem(item);
              }}
            >
              {item.label}
            </Link>
          </li>
          <div className="dropdownContainer">
            // there was dropdown component
          </div>
        </>
      );
    })}
  </ul>
</nav>

我想使用

handleMouseOut
函数停止
handleMouseOver
中的计时器。

javascript reactjs ecmascript-6
1个回答
0
投票

由于

let timer;
在组件主体中声明,因此每次渲染都会重新定义它。因此,当
handleMouseOver
尝试运行
clearTimeout(timer);
时,计时器实际上是未定义的。在这种情况下,可以使用 ref 来保存渲染之间的
timer
值。

所以这样做应该得到你想要的。

const timerRef=useRef(null);

const handleMouseOver = (item) => {
  setNavOver(true);
  if(timerRef.current) clearTimeout(timerRef.current);
  
  for (var i = 0; i < dropdown.length; i += 1) {
    if (dropdown[i].style.display === "none") {
      dropdown[i].style.display = "block";
    }
  }
  if (!currentItem) {
    setCurrentItem(item);
  }
};

const handleMouseOut = (event) => {
  if (!event.relatedTarget || !event.relatedTarget.closest("nav")) {
    setNavOver(false);
    timerRef.current = setTimeout(() => {
      for (var i = 0; i < dropdown.length; i += 1) {
        dropdown[i].style.display = "none";
      }
    }, 700);
  }
};

您还可能会造成内存泄漏,因此如果页面卸载,您还应该通过在 useEffect 返回时清理计时器,如下所示。

useEffect(()=>{
   return()=> {
     if(timerRef.current) clearTimeout(timerRef.current);
},[])
© www.soinside.com 2019 - 2024. All rights reserved.