Refs and the DOM

This section documents React 19.x for the web, using function components and Hooks throughout (class components appear only where React still requires them, such as error boundaries). React Native is out of scope and gets only a pointer. The React 19 additions follow the current official React documentation. This content was generated with the assistance of AI and should be verified against react.dev before being relied on in production, since React APIs continue to evolve between releases.

This section’s bibliography lists the reference material consulted while preparing these pages.

A ref is an escape hatch for values React should not re-render on: a mutable box (ref.current) that persists across renders. Its two uses are holding an arbitrary mutable value and holding a DOM node.

Refs for mutable values

function Stopwatch() {
  const [now, setNow] = useState(0);
  const intervalRef = useRef(null);           // survives re-renders, no re-render on change

  function start() {
    intervalRef.current = setInterval(() => setNow((n) => n + 1), 1000);
  }
  function stop() {
    clearInterval(intervalRef.current);
  }
  // ...
}

Reading or writing ref.current during render is not allowed (it makes render impure); do it in event handlers or Effects. See Referencing Values with Refs.

DOM refs

Pass a ref to a DOM element’s ref attribute and React sets ref.current to the node after commit. Use it to focus, scroll, or measure — things with no declarative equivalent.

function SearchBox() {
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus();                 // focus on mount
  }, []);

  return (
    <>
      <input ref={inputRef} />
      <button onClick={() => inputRef.current.scrollIntoView()}>Reveal</button>
    </>
  );
}

A ref callback runs with the node on mount and null on unmount — useful for a list of nodes:

<li ref={(node) => { if (node) map.set(id, node); else map.delete(id); }} />

See Manipulating the DOM with Refs and Web Programming Basics for the underlying node APIs.

ref as a prop, useImperativeHandle, flushSync

  • React 19: a function component can accept ref as an ordinary prop and forward it to a DOM element. The older forwardRef wrapper still works but is not needed for new code.

    function TextInput({ ref, ...props }) {       // React 19: ref is just a prop
      return <input ref={ref} {...props} />;
    }
  • useImperativeHandle — expose a custom object (not the raw node) as the ref handle, e.g. { focus, scrollToTop }. Rare; prefer props.

  • flushSync (from react-dom) — force React to apply a state update and re-render synchronously so the DOM is up to date before your next line runs (e.g. scroll to a row you just added). Rare and a performance cost.

Avoid refs for anything you can express with state and props. References: useImperativeHandle, flushSync.