如何删除React组件中的窗口EventListener?
代码的平静显示用户鼠标坐标,它可以正常工作。
但是我也想通过单击停止按钮来删除事件处理程序。不幸的是,这似乎是错误的,因为即使在单击按钮后,事件处理程序仍在跟踪和更改位置:
import { useEffect, useState } from 'react'
function MouseCords() {
const [position, setPosition] = useState({ x: 0, y: 0 })
function mouseMoveHandler(event) {
setPosition({
x: event.clientX,
y: event.clientY
})
}
useEffect(() => {
window.addEventListener('mousemove', mouseMoveHandler)
}, [])
return (
<div>
<pre>
x: {position.x}
<br />
y: {position.y}
</pre>
<button
onClick={() =>
window.removeEventListener('mousemove', mouseMoveHandler)
}
>
STOP
</button>
</div>
)
}
我想上下文可能存在问题,但我不是当然该怎么办来解决它。
顺便说一句,这是React组件,我在App.js中使用它:
import MouseCords from './components/MouseCords'
function App() {
return (
<div>
<MouseCords />
</div>
)
}
export default App
This peace of code shows user mouse coordinates, it works properly.
But I also want to remove event handler by clicking the STOP button. Unfortunately, this seems to be wrong somehow because event handler still tracking and changing position even after clicking the button:
import { useEffect, useState } from 'react'
function MouseCords() {
const [position, setPosition] = useState({ x: 0, y: 0 })
function mouseMoveHandler(event) {
setPosition({
x: event.clientX,
y: event.clientY
})
}
useEffect(() => {
window.addEventListener('mousemove', mouseMoveHandler)
}, [])
return (
<div>
<pre>
x: {position.x}
<br />
y: {position.y}
</pre>
<button
onClick={() =>
window.removeEventListener('mousemove', mouseMoveHandler)
}
>
STOP
</button>
</div>
)
}
I guess there might be a problem with context, but I am not sure what to do to solve it.
By the way, this is React component and I am using it in App.js like this:
import MouseCords from './components/MouseCords'
function App() {
return (
<div>
<MouseCords />
</div>
)
}
export default App
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在每个渲染上都会重新计算在组件的最高级别上声明的函数,按钮的
onclick onclick
属性中的匿名函数也将被重新启动。因此,当您尝试删除侦听器时,点击处理程序中的函数引用与侦听器所设置的函数参考不匹配,因此它无法正常工作。最简单的解决方案是使用
usecallback
这将确保仅在第一个渲染时声明该函数(由于空依赖性数组),因此单击处理程序和使用效应函数引用将匹配。您还应该始终提供'nofollow noreferrer“通过从您的
使用
中返回一个函数,该函数将清除我在组件的生命周期中引起的任何副作用的副作用。另外,您可以通过
使用效果
完全处理侦听器,并在每次更改时都使用布尔标志来有条件地添加/删除侦听器。在这种情况下,每次依赖关系数组都会发生变化时,“清理”将运行。A function declared at the top level of a component will be redeclared on every render, as will the anonymous function in the button's
onClick
property. As such, when you try to remove the listener the function reference in the click handler won't match the function reference that the listener was set with and so it won't work.The simplest solution is to declare the function using
useCallback
which will ensure that the function is only declared on first render (due to the empty dependency array) and so the click handler and useEffect function references will match.You should also always provide a 'cleanup' function by returning a function from your
useEffect
that will clean up on unmount any side-effects the useEffect my have caused during the lifecycle of the component.Alternatively you could handle the listener entirely through the
useEffect
and use a boolean flag to conditionally add/remove the listener everytime it changes. In this case the 'cleanup' will run each time there is a change in the dependency array.