useRef returns a mutable object ({ current: value }) that persists across renders without causing a re-render when it changes — the opposite trade-off from useState.
function TextInputWithFocus() {
const inputRef = useRef(null);
return (
<>
<input ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>Focus the input</button>
</>
);
}
Two distinct uses show up constantly:
inputRef.current becomes the actual <input> DOM element once it mounts, letting you call imperative APIs (.focus(), .scrollIntoView()) that have no declarative React equivalent.clearInterval, a "previous value" for comparison, a flag that shouldn't itself cause UI updates.A ref update is invisible to React's rendering — changing ref.current does not schedule a re-render, unlike setState. Using a ref for something that should actually appear on screen is a common mistake; if the UI needs to reflect it, it belongs in state, not a ref.