Reactintermediate 8 min
Hold a value between renders without re-rendering, and reach a real DOM element such as an input.
What a ref is, how to use it to focus an input or keep a value across renders, and how it differs from state.
Sometimes you need to talk to the real DOM (focus an input, scroll a list, measure an element), or remember a value that should not trigger a re-render, such as a timer id. Refs are the tool for both.
useRef(initialValue) returns an object with a single property, .current:
Key facts:
.current is remembered..current does not cause a re-render. That is the main difference from state.ref prop: <input ref={inputRef} />. After mounting, inputRef.current is the real DOM input, so you can call inputRef.current.focus().When to use which:
Do not read or write ref.current while rendering. Use it in event handlers and effects.
inputRef is passed to the input's ref prop, so after the page appears inputRef.current is the real input element..focus() on it, which is a DOM action React does not expose through props.renders is a ref used as a counter. We increment it during render purely to demonstrate: every keystroke re-renders (because text is state), and the count grows. Changing the ref itself does not trigger a render.Click Focus, type a few characters and watch the render count increase. Then add a button that scrolls or selects the text using inputRef.current.select().
ref.current during the first render for a DOM element. It is null until mounted..current. The ref is an object; the value is inside it.useRef gives a stable object with a .current value.Next: building forms.
const ref = useRef(0);
ref.current = 5;function App() {
const inputRef = useRef(null);
const renders = useRef(0);
const [text, setText] = useState("");
renders.current += 1;
function focusInput() {
inputRef.current.focus();
}
function clear() {
setText("");
inputRef.current.focus();
}
return (
<div style={{ fontFamily: "system-ui" }}>
<input
ref={inputRef}
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Type here"
/>
<button onClick={focusInput}>Focus</button>
<button onClick={clear}>Clear</button>
<p>Characters: {text.length}</p>
<p>Component rendered {renders.current} times</p>
</div>
);
}