reactjs - React - 我的自定义钩子在元素外点击有什么问题?
问题描述
我有一个自定义钩子,用于在菜单中的元素之外单击。发生的情况是:当我点击“打开菜单”时,它会打开菜单,当我点击外部时它会关闭它(一切都很好)但是当我再次点击“打开菜单”按钮关闭它(打开后),它关闭它一秒钟,然后再次打开它。我一直在寻找试图找到原因但不能。任何帮助都会很棒。对不起,如果我没有很好地表达我的问题,我不知道如何问得更清楚:) 谢谢!
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])
}
解决方案
菜单组件关闭然后在菜单已经打开时单击按钮时立即再次打开的原因是,当您单击按钮时,useOnClickOutside
会调用侦听器(并关闭菜单)然后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>
)
}
没有改变你的useOnClickOutside
钩子。
推荐阅读
- git - 忽略 Git 中文件的修改
- html - Excel VBA将变量传递给单引号
- c - 不使用 fork() 的两个进程之间的通信
- java - 如何将不同的消息记录到 LoggerFactory 的不同文件中
- html - 如何使用 Flexbox 制作不对称的东西
- javascript - 单击时缩放到元素
- javascript - 反应:无法根据目标正确更新数组
- c# - 使用输出参数从 MethodInfo 创建委托,无需动态调用
- angular - 按键从数组中移除一个对象
- ff4j - 如何根据 RestController 路径参数设置 FF4j RegionFlippingStrategy?