标准答案

  1. useRef 最常见用途是拿 DOM 节点,例如聚焦输入框、测量尺寸或接入第三方库。
  2. useRef 的对象引用在组件生命周期内保持稳定,current 可以被修改,但不会触发组件重新渲染。
  3. 它可以保存 timer id、AbortController、WebSocket、图表实例、编辑器实例等不直接参与渲染的数据。
  4. 它也可以保存最新 props 或 state,供异步回调读取,避免旧闭包问题。
  5. 如果一个值变化后需要反映到 UI,就不应该只放 ref,应使用 state 或外部状态管理。

题目解析

useRef 的关键特性是“稳定引用”和“不触发渲染”。这使它适合保存命令式对象和非 UI 状态。

DOM ref 只是 useRef 的一个场景。复杂组件里,ref 经常用于保存上一次值、请求控制器和第三方实例。

ref 不是 state 的替代品。凡是 UI 需要根据它变化,就要谨慎使用 ref。

代码示例

下面用 ref 保存最新回调,避免事件监听器反复解绑绑定。

TSX
function useWindowKeydown(onKeydown: (event: KeyboardEvent) => void) {
  const handlerRef = useRef(onKeydown)

  useEffect(() => {
    handlerRef.current = onKeydown
  }, [onKeydown])

  useEffect(() => {
    function handleKeydown(event: KeyboardEvent) {
      handlerRef.current(event)
    }

    window.addEventListener('keydown', handleKeydown)
    return () => window.removeEventListener('keydown', handleKeydown)
  }, [])
}

常见误区

  • 把需要驱动 UI 的数据放进 ref,修改后页面不更新。
  • 认为 useRef 只能拿 DOM,不知道它能保存跨渲染的可变值。
  • 用 ref 绕过 React 数据流,导致组件外部无法理解真实状态。

作者信息