Chapter 1 of 4

What a Ref Is

A box React keeps for you, and how it differs from state.

useRef returns an object with a single current property. React hands you the same object on every render, and changing current does not trigger a re-render.

import { useRef } from "react";

function Timer() {
  const intervalId = useRef(null);

  function start() {
    intervalId.current = setInterval(tick, 1000);
  }

  function stop() {
    clearInterval(intervalId.current);
    intervalId.current = null;
  }
}

Ref versus state

  • State is for values the UI displays. Changing it re-renders.
  • Ref is for values the UI does not display. Changing it does not re-render.
  • State updates are asynchronous; a ref changes the moment you assign to it.
  • State must be treated as immutable; a ref is meant to be mutated.
// Displayed on screen -> state
const [count, setCount] = useState(0);

// Never rendered, just remembered -> ref
const renderCount = useRef(0);
renderCount.current = renderCount.current + 1;

Why not a plain variable?

A local variable is recreated on every render, so it forgets. A module-level variable is shared by every instance of the component. A ref is per-instance and survives renders, which is exactly the middle ground.

function Component() {
  let a = 0;                 // reset on every render
  const b = useRef(0);       // one box per component instance, kept forever
}

Good uses for a ref

  • Timeout and interval ids.
  • The previous value of a prop, for comparison.
  • A flag such as 'has this already submitted'.
  • A DOM node you need to focus, measure or scroll.
  • An instance of a third-party library.