Gatsby:事件侦听器不会在 React useEffects 钩子上卸载



我正在使用盖茨比。

我有这个useEffect((钩子,它可以在文档中添加和删除事件侦听器,因此我可以跟踪外部单击以关闭相应的菜单。但是当我导航到另一条路线并打开菜单时,应用程序中断,我收到此错误:

header.js:121 Uncaught TypeError: Cannot read property 'contains' of null
at handleDropdown (header.js:121)
at HTMLDocument.<anonymous> (header.js:134)

每次单击任何地方时,我都会收到此错误三次,因为我有三个事件侦听器。我添加了一个控制台日志,并意识到在路由更改期间,引用的值暂时变为空。我觉得问题是因为标题.js卸载然后重新安装。但是我已经向 useEffect 钩子添加了一个返回,它应该删除事件侦听器并在新路由加载时将它们添加回来。我上面做错了什么吗?

下面是我的函数和useEffect钩子。

// Function to close menus on outside clicks
const handleDropdown = (menuRef, buttonRef, handler, e) => {
console.log(!!menuRef.current, !!buttonRef.current)
if (
menuRef.current.contains(e.target) ||
buttonRef.current.contains(e.target)
) {
return
}
handler(false)
}
useEffect(() => {
document.addEventListener("mousedown", e =>
handleDropdown(mobileMenuRef, menuButtonRef, setShowMobileMenu, e)
)
document.addEventListener("mousedown", e =>
handleDropdown(coursesMenuRef, coursesButtonRef, setShowCoursesMenu, e)
)
document.addEventListener("mousedown", e =>
handleDropdown(
schedulesMenuRef,
schedulesButtonRef,
setShowSchedulesMenu,
e
)
)
document.addEventListener("scroll", handleFixedNavbar)
return () => {
document.removeEventListener("mousedown", e =>
handleDropdown(mobileMenuRef, menuButtonRef, setShowMobileMenu, e)
)
document.removeEventListener("mousedown", e =>
handleDropdown(coursesMenuRef, coursesButtonRef, setShowCoursesMenu, e)
)
document.removeEventListener("mousedown", e =>
handleDropdown(
schedulesMenuRef,
schedulesButtonRef,
setShowSchedulesMenu,
e
)
)
document.removeEventListener("scroll", handleFixedNavbar)
}
}, [])

在JavaScript中,函数通过引用进行比较。这意味着() => {} !== () => {}.当您尝试删除useEffect清理回调中的事件侦听器时,您会传递新定义的函数,但由于上述原因,它们与您定义的现有处理程序不匹配。

如果重构代码以将事件处理程序包含在useEffect钩子中,则可以将相同的钩子局部变量传递给两个(add|remove)EventListener调用:

const useOnClickOutside = (refs, callback) => {
useEffect(() => {
const eventHandler = e => {
if (refs.some(ref => ref.current.contains(e.target))) {
return
} else {
callback(false)
}
}
document.addEventListener("mousedown", eventHandler)
return () => {
document.removeEventListener("mousedown", eventHandler)
}
}, [refs, callback])
}
const YourComponent = () => {
const someRef = useRef()
const someOtherRef = useRef()
useOnClickOutside([someRef, someOtherRef], () => {
console.log("Click outside happened!")
})
return <div>Some Content</div>
}

相关内容

  • 没有找到相关文章

最新更新