A "mutable box" that holds a value. Changing it does not trigger a re-render. It's also used to access DOM elements directly.
Use `useRef` to store values like timers, previous props, or any mutable data that shouldn't cause a re-render.
function Timer() {
const [count, setCount] = useState(0);
// 💾 Ref stores the interval ID
// We need it to clear the timer, but updating it shouldn't render.
const intervalRef = useRef(null);
const start = () => {
intervalRef.current = setInterval(() => {
setCount(c => c + 1);
}, 1000);
};
const stop = () => {
clearInterval(intervalRef.current);
};
return (
<>
<h1>{count}</h1>
<button onClick={start}>Start</button>
<button onClick={stop}>Stop</button>
</>
);
}Pass the ref to a React element accessing the DOM node.
function TextInput() {
const inputRef = useRef(null);
const onClick = () => {
// Access the DOM node directly
inputRef.current.focus();
inputRef.current.style.border = "2px solid blue";
};
return (
<>
<input ref={inputRef} />
<button onClick={onClick}>Focus Input</button>
</>
);
}Never read or write `ref.current` during rendering. React assumes your render output is pure. Only use refs in event handlers or effects.
function Bad() {
const count = useRef(0);
// ❌ WRONG: Writing to ref during render
count.current = count.current + 1;
// ❌ WRONG: Reading ref during render (might be stale)
return <div>{count.current}</div>;
}