Reactjs 我是否正确使用useRef?

Reactjs 我是否正确使用useRef?,reactjs,Reactjs,我想卸载a函数以防止内存泄漏。我最初声明mount的初始值,将其设置为true,然后在useffect中将其声明为false,但我收到一个丑陋的警告,建议我实现一个useRef。我只是想确保我在useEffect中正确地使用它并正确地卸载函数。为了澄清,我正在尝试在卸载组件后卸载地理位置侦听器 import React, { useState, useEffect, useRef } from "react" const initialLocationState = { latitude:

我想卸载a函数以防止内存泄漏。我最初声明mount的初始值,将其设置为true,然后在useffect中将其声明为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
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