Reactjs 我是否正确使用useRef?
我想卸载a函数以防止内存泄漏。我最初声明mount的初始值,将其设置为true,然后在useffect中将其声明为false,但我收到一个丑陋的警告,建议我实现一个useRef。我只是想确保我在useEffect中正确地使用它并正确地卸载函数。为了澄清,我正在尝试在卸载组件后卸载地理位置侦听器Reactjs 我是否正确使用useRef?,reactjs,Reactjs,我想卸载a函数以防止内存泄漏。我最初声明mount的初始值,将其设置为true,然后在useffect中将其声明为false,但我收到一个丑陋的警告,建议我实现一个useRef。我只是想确保我在useEffect中正确地使用它并正确地卸载函数。为了澄清,我正在尝试在卸载组件后卸载地理位置侦听器 import React, { useState, useEffect, useRef } from "react" const initialLocationState = { latitude:
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
import React,{useState,useffect,useRef}来自“React”
常量initialLocationState={
纬度:空,
经度:空,
速度:零
}
常量应用=()=>{
const[count,setCount]=useState(0)
const[isOn,setIsOn]=useState(false)
常量[mousePosition,setMousePosition]=useState({x:null,y:null})
const[status,setStatus]=useState(navigator.onLine)
常数[{纬度、经度、速度},设置位置]=useState(
初始位置状态
)
const DidMountRef=useRef(真)
useffect(()=>{
document.title=`您已单击${count}次`
window.addEventListener(“mousemove”,handleMouseMove)
window.addEventListener(“onine”,扶手线)
window.addEventListener(“脱机”,handleOffline)
navigator.geolocation.getCurrentPosition(handleGeoLocation)
const watchId=navigator.geolocation.watchPosition(handlegeLocation)
return()=>{
window.removeEventListener(“mousemove”,handleMouseMove)
window.removeEventListener(“onine”,handleOnline)
window.removeEventListener(“脱机”,handleOffline)
navigator.geolocation.clearWatch(watchId)
DidMountRef.current=false
}
},[计数])
常量handleOnline=()=>{
设置状态(真)
}
const handleOffline=()=>{
设置状态(假)
}
const handleMouseMove=事件=>{
坐垫({
x:event.pageX,
y:event.pageY
})
}
常量递增计数=()=>{
setCount(prevCount=>prevCount+1)
}
常量切换灯=()=>{
setIsOn(previsOn=>!previsOn)
}
const handlegeLocation=事件=>{
if(DidMountRef){
定位({
纬度:event.coords.latitude,
经度:event.coords.longitude,
速度:event.coords.speed
})
}
}
返回(
柜台
我被点击了{count}次
开关灯
鼠标位置
{JSON.stringify(mousePosition,null,2)}
网络状态
您是{status?“online”:“offline”}
地理定位
纬度是{纬度}
经度是{经度}
你的速度是{速度?速度:“0”}
)
}
导出默认应用程序
一些评论:
const DidMountRef = useRef(true)
useEffect(() => {
...
}
从技术上讲,在调用useffect
回调之前,不会装入组件。但这似乎不会对示例中的逻辑产生太大影响
我不认为您真的希望将
[count]
作为钩子依赖项。如果您只想在装载/卸载时调用效果,则应提供[]
作为依赖项。从:
如果希望运行一个效果并只清理一次(装载和卸载时),可以将空数组([])作为第二个参数传递
我真的不明白你为什么要在
handlegeLocation
内守卫:
const handleGeoLocation = event => {
if (DidMountRef) {
...
}
}
此代码应适用于:
useEffect(() => {
navigator.geolocation.getCurrentPosition(handleGeoLocation)
const watchId = navigator.geolocation.watchPosition(handleGeoLocation)
return () => {
navigator.geolocation.clearWatch(watchId)
}
}, [])
const handleGeoLocation = event => {
setLocation({
latitude: event.coords.latitude,
longitude: event.coords.longitude,
speed: event.coords.speed
})
}
几点意见:
const DidMountRef = useRef(true)
useEffect(() => {
...
}
从技术上讲,在调用useffect
回调之前,不会装入组件。但这似乎不会对示例中的逻辑产生太大影响
我不认为您真的希望将
[count]
作为钩子依赖项。如果您只想在装载/卸载时调用效果,则应提供[]
作为依赖项。从:
如果希望运行一个效果并只清理一次(装载和卸载时),可以将空数组([])作为第二个参数传递
我真的不明白你为什么要在
handlegeLocation
内守卫:
const handleGeoLocation = event => {
if (DidMountRef) {
...
}
}
此代码应适用于:
useEffect(() => {
navigator.geolocation.getCurrentPosition(handleGeoLocation)
const watchId = navigator.geolocation.watchPosition(handleGeoLocation)
return () => {
navigator.geolocation.clearWatch(watchId)
}
}, [])
const handleGeoLocation = event => {
setLocation({
latitude: event.coords.latitude,
longitude: event.coords.longitude,
speed: event.coords.speed
})
}
你能告诉我你想用裁判完成什么吗?一旦数量增加,你是否试图不再收听位置?因为这看起来就是你现在正在做的。我正在尝试在卸载组件后删除地理定位侦听器。你能给我看一下你得到的警告吗,它告诉你使用
useRef
?我想你是在给帽子戴帽子。您正在清除手表,同时将DidMount
设置为false,然后检查watchPosition
的处理程序中的DidMount
是否为false,该处理程序将永远不会被调用。我认为这里根本不需要ref(或装入的变量)。我误解了什么吗?useffect
的清理应该会解决这个问题。不过,请注意,如果handle函数不是纯函数(如果它取决于状态或道具等),则可能会删除其他侦听器,然后可能会发生泄漏。在你的情况下,一切看起来都很好。你能告诉我你想用裁判完成什么吗?一旦数量增加,你是否试图不再收听位置?因为这看起来就是你现在正在做的。我正在尝试在卸载组件后删除地理定位侦听器。你能给我看一下你得到的警告吗,它告诉你使用useRef
?我想你是在给帽子戴帽子。您正在清除手表,同时将DidMount
设置为false,然后检查watchPosition
的处理程序中的DidMount
是否为false,该处理程序将永远不会被调用。我认为这里根本不需要ref(或装入的变量)。我误解了什么吗?useffect
的清理应该会解决这个问题。不过,请注意,如果handle函数不是纯函数(如果它取决于状态或道具等),则可能会删除不同的li