![](/img/trans.png)
[英]How to remove event listener mousedown on component unmount using useeffect react hook?
[英]React useEffect and mousedown listener
我有一个模式,如果用户在它外面点击就会关闭。
方法一- 传递isModalOpened
因此 state 只有在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 数组中删除isModalOpened
。
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);
};
}, []);
问题:我应该传递还是不传递isModalOpened
到 dep 数组?
你不需要它。
原因是如果您toggleModal
为相同的false
值,它不会导致重新渲染。
因此,您无需防范isModalOpened
的值,这会导致您 function 中不包含该变量,从而导致根本不需要依赖项。
不,您不应该将isModalOpen
传递给深层数组,因为在这种情况下,您的效果只会删除并再次添加侦听器。 没必要
方法一将在每次isModalOpened
更改时运行挂钩,在模式关闭时删除全局侦听器。 方法二将在(未)挂载组件时运行挂钩,这意味着全局侦听器将在整个组件生命周期中处于活动状态。
答案取决于您打算如何使用该组件。 我猜你计划在模式打开之前安装组件(因此初始状态为false
),这意味着你的第二种方法将从组件安装到卸载的那一刻监听mousedown
事件。 如果您计划仅在模式打开时安装组件,则此方法将有效。 但你不是,这意味着你应该只在模式打开时设置全局侦听器。
第一种方法是正确的。
*编辑
但是您可以在 if 语句中删除isModalOpened
检查。
我建议对此采取一些不同的方法。 我会在这里将clickOut
function 包装在useCallback
中,它具有作为toggleModal
和ref
的依赖项,并将clickOut
作为 useEffect 中的依赖useEffect
。 这样,每当您ref
或toggleModal
更改时,您都会对 clickOut 有一个新的引用,如果您对clickOut
有新的引用,您将在clickOut
中再次分配监听useEffect
。 这将帮助您在每个渲染上创建不必要clickOut
function 并优化渲染。
因此,根据我的建议,您的代码将如下所示:
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]);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.