React文档中的removeEventListener方法不起作用。

4
我正在尝试制作一个可拖动的React组件,代码总是能够达到“移除监听器”模块,但之后组件仍然会继续粘在我的鼠标上,所以显然我搞砸了移除监听器的步骤,不过我不确定具体是哪里错了——我传递给document.add/removeEventListener的两个函数肯定是相同的吧?
useEffect(() => {
            if (dragging && !prevDragging) {
                document.addEventListener("mousemove", onMouseMove)
                document.addEventListener("mouseup", onMouseUp)
            } else if (!dragging && prevDragging) {
                console.log('removing listeners')
                document.removeEventListener("mousemove", onMouseMove)
                document.removeEventListener("mouseup", onMouseUp)
                }
            }
        )

 const onMouseMove = (e) => {
            if (!dragging) return;
            setPos({
                x: e.pageX - rel.x,
                y: e.pageY - rel.y
            });
        e.stopPropagation();
        e.preventDefault();
    }

const onMouseUp = (e) => {
        setDragging(false);
        e.stopPropagation();
        e.preventDefault();
    }
2个回答

5

只需使用React的useCallback函数,React就会记住这些函数是相同的。

const onMouseMove = React.useCallback((e) => {
  if (!dragging) return;
  setPos({
    x: e.pageX - rel.x,
    y: e.pageY - rel.y,
  });
  e.stopPropagation();
  e.preventDefault();
}, []);

const onMouseUp = React.useCallback((e) => {
  setDragging(false);
  e.stopPropagation();
  e.preventDefault();
}, []);

0
在每次渲染React组件时都会创建一个新的函数。因此,如果您在浏览器的“开发人员工具”中检查“事件侦听器”,您将看到在每次渲染后添加了几个侦听器。因此,即使您删除了最新的事件侦听器,旧的事件侦听器仍然存在。
因此,本质上我想说的是:-
const onMouseMove = (e) => {
            if (!dragging) return;
            setPos({
                x: e.pageX - rel.x,
                y: e.pageY - rel.y
            });
        e.stopPropagation();
        e.preventDefault();
    }

在第一次渲染时不同于

const onMouseMove = (e) => {
            if (!dragging) return;
            setPos({
                x: e.pageX - rel.x,
                y: e.pageY - rel.y
            });
        e.stopPropagation();
        e.preventDefault();
    }

在第二次渲染及以后,它们在逻辑上是等价的,但并不指向同一个函数。


那么,我定义的useEffect应该在调用removeEventListener之前只调用一次addEventListener -- 但是你说这并不重要,因为在组件的每次渲染中函数都是不同的?那么我如何引用相同的函数呢?谢谢! - shadowstuff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接