Conceptly
← All Concepts
🎯

Ref

Imperative AccessReact's escape hatch for remembering mutable values and touching DOM nodes directly

A ref is a mutable container React preserves across renders. It can point to a DOM node or hold a value that should stay available without causing another render.

Architecture Diagram

🔗 Relationship

Dashed line animations indicate the flow direction of data or requests

Why do you need it?

Not every value belongs in state. If a change should not recalculate the screen, putting it in state adds unnecessary rerenders. And some work, such as focus management or scroll control, needs a direct handle to a real DOM node.

Why did this approach emerge?

React pushed UI toward a declarative model, but browsers and third-party libraries still expose many imperative APIs. Ref exists because teams still need a safe way to cross that boundary when declarative rendering is not the right fit.

How does it work inside?

Calling useRef returns an object with a current property, and React keeps that object stable across renders. When attached to a JSX element, React writes the real DOM node into current during commit. For ordinary values, developers can update current manually without triggering another render.

In Code

Pointing at a DOM node to control focus

import { useRef } from "react";

export function SearchInput() {
  const inputRef = useRef<HTMLInputElement | null>(null);

  function handleFocus() {
    inputRef.current?.focus();
  }

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleFocus}>Move focus</button>
    </>
  );
}

A ref acts as a handle to the real DOM node after commit, which makes imperative actions like focus straightforward.

Mutable values that do not affect UI can live in a ref

import { useRef } from "react";

export function DragSurface() {
  const dragStartX = useRef<number | null>(null);

  function handleMouseDown(event: React.MouseEvent<HTMLDivElement>) {
    dragStartX.current = event.clientX;
  }

  return <div onMouseDown={handleMouseDown}>Start drag</div>;
}

A drag coordinate needs to persist across renders, but it does not need to trigger one immediately. That is the kind of value refs are for.

When should you use it?

In practice, refs are common for autofocus, drag coordinates, previous-prop tracking, and integrating chart or editor libraries. But once refs start carrying values that should visibly affect UI, it usually means state is the right home instead.

Moving focus and controlling scroll positionStoring timer IDs and previous valuesKeeping external library instances availableRemembering mutable data that should not rerender UI