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

React hooks - Set a timeout inside useEffect but be able to clear it from a mouse event?

这是一个经典的菜单案例,点击按钮打开,如果没有按钮在 5 秒内隐藏 activity。我们有 2 个状态变量。 open 和 active,对应两种不同的状态 = menu is open, and active (being used)。我使用单击按钮设置打开变量,然后实际上我开始了 5 秒超时。现在,如果用户将鼠标悬停在菜单上,我将活动 属性 设置为 true 并尝试清除超时。但这是行不通的。意思是,超时变量在应该清除它的代码中始终为 null。

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

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,但即便如此,计时器仍为空。如何解决这个问题?请帮忙。

只要您的组件 re-renders,timer 变量将为 re-declared,初始值为 null。因此,当 useEffect 钩子在其任何依赖项更改时执行时,timer 变量为 null.

您可以通过确保 timer 变量的值在组件的 re-renders 中保持不变来解决问题。要在 re-renders 中保留该值,请使用 useRef 挂钩保存 setTimeout 的 ID 或将其保存在状态中,即 useState 挂钩。