React document.removeEventListener 不起作用
Posted
技术标签:
【中文标题】React document.removeEventListener 不起作用【英文标题】:React document.removeEventListener is not working 【发布时间】:2020-09-19 19:16:23 【问题描述】:我正在尝试制作一个可拖动的 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();
【问题讨论】:
【参考方案1】:在每次渲染 React 组件时,都会创建一个新函数。因此,如果您在浏览器的developer tools
中检查event listeners
,您会看到在每次渲染后添加了其中的几个。因此,即使您删除了最新的事件监听器,旧的仍然存在。
所以本质上我要说的是函数:-
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 - 但你说这没关系,因为在组件的每个渲染上,功能都是不同的?那么我如何引用相同的函数呢?谢谢!【参考方案2】:只需使用 Reacts 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();
, []);
【讨论】:
以上是关于React document.removeEventListener 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
import * as react from 'react' 与 import react from 'react' 有啥区别
“使用 JSX 时,React 必须在范围内”(react/react-in-jsx-scope 与 index.js 上的“window.React = React”)