Capítulo 62 de 116

Chapter 62: useRef

Core Idea

useRef(initialValue) is the API reference for the mutable-box pattern from Ch 34: returns { current: initialValue }, a stable object across renders whose .current can be freely read/written without causing or being subject to re-renders.

Key Concepts

  • Signature: const ref = useRef(initialValue)initialValue is only used on the very first render; the same ref object identity persists for the component's whole lifetime.
  • Two primary uses: (1) holding a value that needs to persist across renders but shouldn't trigger one when it changes (timers, counters, previous-value tracking), and (2) receiving a DOM node when passed to an element's ref attribute (Ch 35).
  • Mutating ref.current doesn't re-render — this is the defining, deliberate difference from useState; if a UI update needs to reflect the change, a ref is the wrong tool and state is the right one.
  • Don't read/write .current during rendering — same rule as Ch 34: confine ref access to event handlers and Effects to keep the render function pure (Ch 18); the one exception is lazily initializing a ref's value on first render (checking if (ref.current === null) before setting it once), which is a recognized, safe pattern.
  • A ref passed to a DOM element attaches after commit (Ch 22) — ref.current is null until the element mounts, and is set back to null on unmount.

Code Examples

function Stopwatch() {
  const intervalRef = useRef(null);
  function handleStart() {
    intervalRef.current = setInterval(tick, 1000);
  }
  function handleStop() {
    clearInterval(intervalRef.current);
  }
}
  • What it demonstrates: an interval ID that must survive across renders and be accessible in two separate handlers, without ever needing to trigger a re-render itself.

Key Takeaways

  1. If mutating the value should update the screen, use useState; if not, use useRef.
  2. A DOM ref's .current is only guaranteed populated after commit — never assume it's set during the render body.
  3. The "lazy one-time initialization" pattern (checking ref.current === null inside the render body) is the sole sanctioned exception to "never read/write refs during render."

Connects To

  • Ch 34 (Referencing Values with Refs) and Ch 35 (Manipulating the DOM with Refs): the full conceptual treatment this reference formalizes.
  • Ch 56 (useImperativeHandle): customizing what a parent's ref to this component actually receives.