Skip to content

Ref Hook

字数
462 字
阅读时间
3 分钟

useRef

允许组件保存一些不用于渲染的信息:

  • 希望组件"记住"某些信息,但又不想让这些信息触发新的渲染

useRef 使用场景

  1. 存储 DOM 元素引用
tsx
function VideoPlayer() {
  const videoRef = useRef(null)

  const play = () => {
    videoRef.current.play()
  }

  const pause = () => {
    videoRef.current.pause()
  }

  return (
    <div>
      <video ref={videoRef}>
        <source src="video.mp4" type="video/mp4" />
      </video>
      <button onClick={play}>播放</button>
      <button onClick={pause}>暂停</button>
    </div>
  )
}
  1. 保存定时器 ID
tsx
function AutoSave({ onSave }) {
  const saveTimerRef = useRef(null)

  useEffect(() => {
    // 每 5 秒自动保存
    saveTimerRef.current = setInterval(() => {
      onSave()
    }, 5000)

    return () => {
      // 清理定时器
      clearInterval(saveTimerRef.current)
    }
  }, [onSave])

  return <div>自动保存中...</div>
}
  1. 记录前一次的值
tsx
function MessageList() {
  const [messages, setMessages] = useState([])
  const prevMessagesRef = useRef([])

  useEffect(() => {
    // 保存前一次的消息列表
    prevMessagesRef.current = messages
  }, [messages])

  const hasNewMessages = messages.length > prevMessagesRef.current.length

  return (
    <div>
      {hasNewMessages && <div>有新消息!</div>}
      {/* 消息列表渲染 */}
    </div>
  )
}
  1. 存储可变值(不触发重渲染)
tsx
function StopWatch() {
  const [time, setTime] = useState(0)
  const intervalRef = useRef(null)
  const isRunningRef = useRef(false)  // 不需要触发重渲染的状态

  const start = () => {
    if (isRunningRef.current) return
    isRunningRef.current = true
    intervalRef.current = setInterval(() => {
      setTime(t => t + 1)
    }, 1000)
  }

  const stop = () => {
    isRunningRef.current = false
    clearInterval(intervalRef.current)
  }

  return (
    <div>
      <div>时间: {time}秒</div>
      <button onClick={start}>开始</button>
      <button onClick={stop}>停止</button>
    </div>
  )
}

useRef 特点

  • ref.current 的变化不会触发组件重新渲染
  • ref 值在组件的整个生命周期内保持不变
  • 适合存储那些不需要参与 UI 渲染的值
  • 常用于存储 DOM 引用、定时器 ID、前一次的值等

使用建议

  • 如果值需要参与渲染,使用 useState
  • 如果值仅用于存储/记忆且不需要触发重渲染,使用 useRef
  • 不要在渲染期间读取或写入 ref.current

贡献者

页面历史