Ref
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
🔗 RelationshipDashed line animations indicate the flow direction of data or requests
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.
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.
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.
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.
Refs are often confused with state because both can remember values, but their intent differs. State drives rendering. Refs hold values or node handles outside the render loop. Compared with Virtual DOM, refs are the exception path rather than the normal update path.
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.