React挂钩-在useEffect中设置超时,但能够从鼠标事件中清除它



这是一个经典的菜单案例,点击按钮即可打开,如果没有活动,则在5秒内隐藏。我们有两个状态变量。open和active,对应于两种不同的状态=菜单是open和active(正在使用(。我通过点击按钮来设置开放变量,然后实际上我开始了5秒的超时。现在,如果用户将鼠标悬停在菜单上,我会将active属性设置为true,并尝试清除超时。但这是行不通的。也就是说,超时变量在应该清除它的代码中总是为空

这里有一些代码可以帮助您理解:

let [open, openMenu] = useState(false)
let [active, activateMenu] = useState(false)
let timer = null;
useEffect(() => {
if(open && !active) {
timer = setTimeout(() => setOpen(false), 5000)
}
if(open && active) {
if(timer) {
clearTimeout(timer)
}
}
}, [open, active])
// Triggered via the UI on a button click
openMenuhandler() {
setOpen(true)
}
// Triggered via the UI on mouseenter
// identifies that the menu is being used, when mouse is over it
setMenuActive() {
activateMenu(true)
}
// Triggered via the UI on mouseleave
setMenuInActive() {
activateMenu(false)
}
// other code here on

现在,超时永远不会被清除。不管怎样,菜单都会在5秒内隐藏。还有别的办法吗?我甚至尝试过将clearTimeout移到mouseLeave,但即使这样,计时器也是空的。如何解决此问题?请帮忙。

无论何时重新渲染组件,timer变量都将重新声明为初始值null。因此,当useEffect钩子在其任何依赖项发生变化时执行时,timer变量为null

您可以通过确保timer变量的值在组件的重新渲染中保持不变来解决这个问题。要在重新渲染期间保持该值,请使用useRef钩子保存setTimeout的id,或者将其保存在状态中,即useState钩子。

最新更新