Javascript React useffect和mousedown侦听器
我有一个模式,如果用户在其外部单击,该模式将关闭 接近一号-通过Javascript React useffect和mousedown侦听器,javascript,reactjs,Javascript,Reactjs,我有一个模式,如果用户在其外部单击,该模式将关闭 接近一号-通过isModalOpened,因此只有当isModalOpened为真时,状态才会在单击时更新 const [isModalOpened, toggleModal] = useState(false); const ref = useRef(null); const clickOut = (e) => { if (!ref.current.contains(e.target) && isModalOpene
isModalOpened
,因此只有当isModalOpened
为真时,状态才会在单击时更新
const [isModalOpened, toggleModal] = useState(false);
const ref = useRef(null);
const clickOut = (e) => {
if (!ref.current.contains(e.target) && isModalOpened) {
toggleModal(false);
}
};
React.useEffect(() => {
window.addEventListener('mousedown', clickOut);
return () => {
window.removeEventListener('mousedown', clickOut);
};
}, [isModalOpened]);
方法二-从dep阵列中删除ismodaloped
const [isModalOpened, toggleModal] = useState(false);
const ref = useRef(null);
const clickOut = (e) => {
if (!ref.current.contains(e.target)) {
toggleModal(false);
}
};
React.useEffect(() => {
window.addEventListener('mousedown', clickOut);
return () => {
window.removeEventListener('mousedown', clickOut);
};
}, []);
问题:我应该传递还是不传递ismodaloped
到dep数组?您不需要它
原因是,如果将切换到相同的false
值,则不会导致重新渲染
因此,您不必担心ismodalopend
的值会导致函数中不包含变量,这会导致根本不需要依赖关系。不,您不应该将isModalOpen
传递到深度数组,因为在这种情况下,您的效果只会删除并再次添加侦听器。这是不必要的方法每次ismodaloped
更改时,都会运行钩子,在模式关闭时删除全局侦听器。方法2将在(未)装入组件时运行钩子,这意味着全局侦听器将在整个组件生命周期中处于活动状态
答案取决于您计划如何使用该组件。我猜您计划在模态打开之前安装组件(因此为false
初始状态),这意味着您的第二种方法将从安装组件到卸载组件的那一刻监听mousedown
事件。如果您计划仅在打开模式时安装组件,则此方法将有效。但您没有,这意味着您应该仅在打开模式时设置全局侦听器
第一种方法是正确的
*编辑
但是您可以删除if语句中的ismodalopend
检查。我建议对此采取一种不同的方法。在这里,我将clickOut
函数包装在useCallback
中,它的依赖项为toggleModal
和ref
,而clickOut
的依赖项为useffect
。这样,每当ref
或toggleModal
更改时,您就有了一个新的clickOut
参考,如果您有了新的clickOut
参考,您的侦听器将在useffect
中重新分配。这将有助于您在每次渲染时取消不必要的单击
函数创建,并优化渲染
因此,根据我的建议,您的代码将如下所示:
const [isModalOpened, toggleModal] = useState(false);
const ref = useRef(null);
const clickOut = useCallback((e) => {
if (!ref.current.contains(e.target) && isModalOpened) {
toggleModal(false);
}
}, [isModalOpened, ref]);
React.useEffect(() => {
window.addEventListener('mousedown', clickOut);
return () => {
window.removeEventListener('mousedown', clickOut);
};
}, [clickOut]);
如果创建对话框,请不要使用窗口,而是放置一个全屏固定透明div或半透明div,并将事件附加到此对话框。为什么?因为它允许你在对话中有对话…嗯,很有趣。因此,有两个答案是为了删除依赖项,而您的答案是为了保留依赖项。这两个答案是关于ismodalopend
检查您的if语句,但是我的答案是正确的。您可以通过在浏览器的开发工具中检查全局侦听器来检查这一点(或者更简单地说,通过使用console.log并在调用clickOut
函数时进行检查)。我喜欢,这似乎是最好的解决方案。我希望在react方面非常有经验的人能证实这一点。喜欢肯定的表演