Everything so far has been declarative: you describe what the screen should look like for a given state, and React 7,897 works out the DOM operations. That covers most of an interface, but not all of it. Moving focus, playing a video, measuring how wide a heading turned out to be, scrolling a list to the bottom — none of these are values you can describe. For those you need the real node, at the moment the user acts.
A ref is React's escape hatch: a plain object with a single current property that survives every re-render and never triggers one. It serves two distinct purposes, which this section separates carefully. On its own, a ref is a mutable box for a timer ID, a previous value, a WebSocket. Passed to a JSX element's ref attribute, it becomes a handle on the DOM node React created — React writes the node into current when it commits and clears it when the node goes away.

The DOM API itself — focus, scrollIntoView, getBoundingClientRect, IntersectionObserver — is Front-End Web Development material. What follows is how React gives you a node to call those methods on, when the node is actually there, and how to keep imperative code from breaking the declarative model around it.