【发布时间】:2020-03-08 08:24:59
【问题描述】:
我想卸载我的函数以防止内存泄漏。我一开始是声明 mount 的初始值,将其设置为 true,然后在 useEffect 中将其声明为 false,但我收到了一个丑陋的警告,建议我实现 useRef。我只是想确保我正确使用它并正确卸载我的 useEffect 中的功能。为了澄清,我试图在卸载组件后卸载地理定位侦听器。
import React, { useState, useEffect, useRef } from "react"
const initialLocationState = {
latitude: null,
longitude: null,
speed: null
}
const App = () => {
const [count, setCount] = useState(0)
const [isOn, setIsOn] = useState(false)
const [mousePosition, setMousePosition] = useState({ x: null, y: null })
const [status, setStatus] = useState(navigator.onLine)
const [{ latitude, longitude, speed }, setLocation] = useState(
initialLocationState
)
const DidMountRef = useRef(true)
useEffect(() => {
document.title = `You have clicked ${count} times`
window.addEventListener("mousemove", handleMouseMove)
window.addEventListener("onine", handleOnline)
window.addEventListener("offline", handleOffline)
navigator.geolocation.getCurrentPosition(handleGeoLocation)
const watchId = navigator.geolocation.watchPosition(handleGeoLocation)
return () => {
window.removeEventListener("mousemove", handleMouseMove)
window.removeEventListener("onine", handleOnline)
window.removeEventListener("offline", handleOffline)
navigator.geolocation.clearWatch(watchId)
DidMountRef.current = false
}
}, [count])
const handleOnline = () => {
setStatus(true)
}
const handleOffline = () => {
setStatus(false)
}
const handleMouseMove = event => {
setMousePosition({
x: event.pageX,
y: event.pageY
})
}
const incrementCount = () => {
setCount(prevCount => prevCount + 1)
}
const toggleLight = () => {
setIsOn(previsOn => !previsOn)
}
const handleGeoLocation = event => {
if (DidMountRef) {
setLocation({
latitude: event.coords.latitude,
longitude: event.coords.longitude,
speed: event.coords.speed
})
}
}
return (
<>
<h2>Counter</h2>
<button onClick={incrementCount}>I was clicked {count} times</button>
<h2>Toggle Light</h2>
<img
src={
isOn
? "https://icon.now.sh/highlight/fd0"
: "https://icon.now.sh/highlight/aaa"
}
style={{
height: "50px",
width: "50px"
}}
onClick={toggleLight}
alt='Lightbulb'
></img>
<h2>Mouse Position</h2>
{JSON.stringify(mousePosition, null, 2)}
<br />
<h2>Network Status</h2>
<p>
you are <strong>{status ? "online" : "offline"}</strong>
</p>
<h2>GeoLocation</h2>
<p>Latitude is {latitude}</p>
<p>longitude is {longitude}</p>
<p>Your speed is {speed ? speed : "0"}</p>
</>
)
}
export default App
【问题讨论】:
-
你能告诉我你想用 ref 完成什么吗?一旦计数增加,您是否试图不再听位置?因为看起来这就是你现在正在做的事情。
-
我试图在组件卸载后删除地理位置监听器
-
你能告诉我你得到的警告,告诉你使用
useRef吗? -
我想你在这里是在把帽子戴在帽子上。您正在清除手表并将
DidMount同时设置为false,然后在watchPosition的处理程序中检查DidMount是否为false,该处理程序永远不会被调用。我认为您根本不需要 ref (或mounted变量)。我是不是误会了什么? -
useEffect的清理工作应该会解决这个问题。虽然,请注意,如果句柄函数不是纯函数(如果它取决于状态或道具等),您可能会删除不同的侦听器,然后您可能会发生泄漏。在你的情况下,一切看起来都很好。
标签: reactjs