Files
skillhub-088-vercel-react-b…/rules/rerender-use-ref-transient-values.md
2026-07-13 21:36:17 +08:00

1.7 KiB


title: Use useRef for Transient Values impact: MEDIUM impactDescription: 避免频繁更新时触发不必要的重渲染 tags: rerender, useref, state, performance

使用 useRef 存储临时值

当一个值变化频繁,且你不希望每次更新都触发重渲染时(例如鼠标追踪器、定时器、临时标记),应将其存储在 useRef 中,而非 useState。用组件状态管理 UI,用 ref 管理临时的 DOM 相关值。更新 ref 不会触发重渲染。

错误做法(每次更新都渲染):

function Tracker() {
  const [lastX, setLastX] = useState(0)

  useEffect(() => {
    const onMove = (e: MouseEvent) => setLastX(e.clientX)
    window.addEventListener('mousemove', onMove)
    return () => window.removeEventListener('mousemove', onMove)
  }, [])

  return (
    <div
      style={{
        position: 'fixed',
        top: 0,
        left: lastX,
        width: 8,
        height: 8,
        background: 'black',
      }}
    />
  )
}

正确做法(追踪时不触发重渲染):

function Tracker() {
  const lastXRef = useRef(0)
  const dotRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const onMove = (e: MouseEvent) => {
      lastXRef.current = e.clientX
      const node = dotRef.current
      if (node) {
        node.style.transform = `translateX(${e.clientX}px)`
      }
    }
    window.addEventListener('mousemove', onMove)
    return () => window.removeEventListener('mousemove', onMove)
  }, [])

  return (
    <div
      ref={dotRef}
      style={{
        position: 'fixed',
        top: 0,
        left: 0,
        width: 8,
        height: 8,
        background: 'black',
        transform: 'translateX(0px)',
      }}
    />
  )
}