该代码适用于
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
中的计时器。
由于
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);
},[])