我有一个Backdrop_DIV
,它是基于open
的Dropdown组件呈现的。
{open &&
<LS.Backdrop_DIV
onClick={handleBackdropClick}
ref={backdrop_ref}
>
Backdrop
</LS.Backdrop_DIV>
}
如果用户滚动(Backdrop_DIV
),我希望touchmove
消失。
肥胖:这是移动视图。
const handleTouchMove = useCallback(()=>{
setOpen(false);
},[]);
useEffect(() => {
if (open) {
// ATTACHING THE EVENT LISTENR
backdrop_ref.current.addEventListener('touchmove', handleTouchMove );
}
// ATTEMPT TO REMOVE THE EVENT LISTENER
return () =>
backdrop_ref.current.removeEventListener('touchmove', handleTouchMove);
},[open,handleScroll]);
它可以工作,但是如果在我的useEffect
返回中试图清除事件侦听器时失败了。有办法吗?
错误:
react-dom.development.js:20313未捕获的TypeError:无法读取null的属性'removeEventListener'
此错误非常明显,因为Backdrop_DIV
在运行时不再挂载。
问题
在这种情况下,我是否需要麻烦删除事件监听器?我该怎么办?
答案 0 :(得分:0)
从Carlene在评论中建议的问题,我想说没有必要删除事件侦听器,因为它将由垃圾收集器处理,尽管某些较旧的浏览器在这种情况下可能会泄漏内存。
If a DOM Element is removed, are its listeners also removed from memory?
但是,我也找到了一种方法,可以在卸除Backdrop_DIV
之前删除侦听器,并且可以:
lastOpenState_ref
useRef()
来跟踪先前的渲染open
状态,因此我可以检测到将卸载Backdrop_DIV
(open === false
)的渲染然后在该渲染期间删除监听器。import React, {useState, useEffect, useRef, useCallback} from 'react';
function MyComponent() {
const [open,setOpen] = useState(false);
const backdrop_ref = useRef(null);
const lastOpenState_ref = useRef(false);
const handleBackdropTouchMove = useCallback(() => {
setOpen(false);
},[]);
// BLOCK TO REMOVE EVENT LISTENER FROM backdrop_ref
// SINCE IT'S IMPOSSIBLE TO REMOVE FROM THE useEffect RETURN
// BECAUSE THE backdrop_ref IS NULL WHEN IT RUNS
if (lastOpenState_ref.current === true && open === false) {
backdrop_ref.current.removeEventListener('touchmove', handleBackdropTouchMove);
}
lastOpenState_ref.current = open;
// EFFECT TO ATTACH 'touchmove' EVENT LISTENER ON 'backdrop_ref.current'
useEffect(() => {
if (open) {
backdrop_ref.current.addEventListener('touchmove', handleBackdropTouchMove);
}
},[open,handleBackdropTouchMove]);
// RETURN STATEMENT
return(
<LS.Container_DIV>
{open &&
<LS.Backdrop_DIV
onClick={handleBackdropClick}
ref={backdrop_ref}
>
</LS.Backdrop_DIV>
}
<SomeOtherStuff/>
</LS.Container_DIV>
);
}