如何从正在卸载的背景中删除事件侦听器?

cbd*_*per 5 javascript addeventlistener reactjs react-hooks removeeventlistener

我有一个Backdrop_DIV基于open下拉组件的a 呈现的。

{open &&
  <LS.Backdrop_DIV
    onClick={handleBackdropClick}
    ref={backdrop_ref}
  >
    Backdrop
  </LS.Backdrop_DIV>
}
Run Code Online (Sandbox Code Playgroud)

Backdrop_DIV如果用户滚动 ( touchmove),我希望它消失。

Obs:这是一个移动视图。

const handleTouchMove = useCallback(()=>{
    setOpen(false);
  },[]);
Run Code Online (Sandbox Code Playgroud)
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]);
Run Code Online (Sandbox Code Playgroud)

它有效,但如果在我尝试清除我的useEffect. 有没有办法做到这一点?

错误:

react-dom.development.js:20313 未捕获的类型错误:无法读取 null 的属性“removeEventListener”

这个错误很明显,因为Backdrop_DIV它在运行时不再挂载。

在这种情况下,我需要费心删除事件侦听器吗?我能做什么?

cbd*_*per 0

根据 Carlene 在评论中推荐的问题,我想说没有必要删除事件侦听器,因为它将由垃圾收集器处理,尽管某些较旧的浏览器在这种情况下可能会泄漏内存。

如果删除 DOM 元素,其侦听器是否也会从内存中删除?

而且,我找到了一种在卸载之前删除侦听器的方法,Backdrop_DIV并且它有效:

  • 我添加了lastOpenState_ref useRef()对先前渲染状态的跟踪,以便我可以检测将卸载( )open的渲染,并在该渲染期间删除侦听器。Backdrop_DIVopen === 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>
  );
}
Run Code Online (Sandbox Code Playgroud)