我有一个自定义钩子,用于在菜单中的元素外单击。发生的情况是:当我点击“打开菜单”时,它会打开菜单,当我在外面点击它时会关闭它(一切都很好)但是当我再次点击“打开菜单”按钮关闭它时(打开它后),它将其关闭一秒钟,然后再次打开。我一直在寻找试图找到原因但不能。任何帮助都会很棒。对不起,如果我没有很好地表达我的问题,我不知道如何问得更清楚:)谢谢!!
const { useState, useRef } = React;
const App = () => {
const [showMenu, setShowMenu] = React.useState(false)
return (
<div>
<div className="menu-section-conatainer">
<button
className={"menu-link"}
onClick={() => {
setShowMenu(true)
}}
name={title}
>
open menu
</button>
</div>
<Menu
showState={showMenu}
clickHandler={setShowMenu}
>
{children}
</Menu>
</div>
)
}
const Menu = ({ children, clickHandler, showState}) => {
const ref = useRef()
useOnClickOutside(ref, () => clickHandler(false))
return (
<div
className="menu-expanded-wrapper"
>
<div ref={ref} className="menu-expanded">
{children}
</div>
</div>
)
}
const useOnClickOutside = (ref, handler) => {
React.useEffect(() => {
const listener = event => {
if (!ref.current || ref.current.contains(event.target)) {
return
}
handler(event)
}
document.addEventListener("mousedown", listener)
document.addEventListener("touchstart", listener)
return () => {
document.removeEventListener("mousedown", listener)
document.removeEventListener("touchstart", listener)
}
}, [ref, handler])
}
答案 0 :(得分:1)
在菜单已经打开的情况下单击按钮时,您的菜单组件关闭然后立即再次打开的原因是,当您单击按钮时,useOnClickOutside
中的侦听器被调用(并关闭菜单),然后 {调用按钮上的 {1}} 函数(并打开菜单)。
您可以通过将 onClick
的使用移至 useOnClickOutside
组件并将引用放在作为按钮和菜单的父元素的元素上来解决此问题,以便忽略对按钮的点击出于“外”的目的。此外,这可能是一种更好的结构,因此打开/关闭逻辑仅包含在 App
组件中。
然后您应该更新按钮的 App
函数,使其切换 onClick
而不是仅仅将其值设置为 showMenu
。您只需使用 true
即可完成此操作。
这是一个例子:
setShowMenu(prev => !prev)
您的 const App = () => {
const [showMenu, setShowMenu] = React.useState(false)
const ref = React.useRef()
useOnClickOutside(ref, () => setShowMenu(false))
return (
<div ref={ref}>
<div className="menu-section-conatainer">
<button
className={"menu-link"}
onClick={() => {
setShowMenu(prev => !prev)
}}
name="Toggle Menu"
>
{showMenu ? "Hide Menu" : "Show Menu"}
</button>
</div>
<Menu showState={showMenu}>
Menu Items
</Menu>
</div>
)
}
const Menu = ({ children, showState}) => {
return (
<div className="menu-expanded-wrapper">
<div className={ showState ? "menu-expanded" : "menu-collapsed" }>
{children}
</div>
</div>
)
}
钩子没有变化。