Q158: useRef, DOM Refs and Mutable Instance Values
What Interviewers Want To Evaluate
This question checks whether you understand refs as mutable containers outside the render data flow. Interviewers want DOM refs, mutable values, no re-render on ref change, previous value tracking, timers, imperative APIs, callback refs, and React 19 initial value expectations.
Senior answers should explain when refs are appropriate and when state is required.
Short Interview Answer
useRef returns a stable object whose .current value can be mutated without causing a re-render. It is commonly used for DOM nodes, timers, imperative handles, previous values, and values that need to survive renders without affecting UI. If changing a value should update the screen, use state instead. In React 19 TypeScript patterns, refs should be initialized explicitly, usually with null for DOM refs.
Detailed Interview Answer
useRef creates a stable container.
const inputRef = useRef(null);
React keeps the same ref object across renders.
inputRef.current;
Changing .current does not trigger a render.
DOM Refs
DOM refs let React give you access to a host element.
function SearchBox() {
const inputRef = useRef(null);
function focusInput() {
inputRef.current?.focus();
}
return <input ref={inputRef} />;
}
This is useful for focus, selection, measurement, and imperative browser APIs.
Mutable Instance Values
Refs can store mutable values that should survive renders.
const timeoutIdRef = useRef(null);
Common examples:
timer IDs
latest callback
previous values
DOM nodes
external library instances
abort controllers
No Re-Render
This does not update the UI:
countRef.current += 1;
If the screen must reflect the new value, use state.
setCount((count) => count + 1);
Previous Value Pattern
function usePrevious(value) {
const ref = useRef(undefined);
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
The ref stores data across renders without causing another render.
Latest Callback Pattern
Refs can avoid stale callback reads in subscriptions.
const latestOnChange = useRef(onChange);
useEffect(() => {
latestOnChange.current = onChange;
}, [onChange]);
This should be used carefully. New React patterns like effect events may be clearer where available.
Callback Refs
Callback refs run when a node is attached or detached.
<div ref={(node) => {
if (node) {
measure(node);
}
}} />
They are useful for dynamic lists or immediate node handling.
Imperative APIs
Some third-party widgets require imperative instances.
const chartRef = useRef(null);
Initialize and clean up in effects.
useEffect(() => {
chartRef.current = createChart(containerRef.current);
return () => {
chartRef.current?.destroy();
};
}, []);
Common Mistakes
A common mistake is using refs to store data that should be rendered.
Another mistake is reading or writing refs during render in ways that make output depend on mutable external state.
Another mistake is forgetting cleanup for imperative instances.
Senior Trade-Offs
Refs are escape hatches. They are right for imperative integration and non-visual mutable values.
State is right for visual data. Props are right for parent-controlled data. Refs are right when mutation should not trigger rendering.
Code or Design Example
function AutoFocusInput() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
return <input ref={inputRef} />;
}
This synchronizes React with the browser focus API.
Debugging Workflow
When ref behavior is confusing:
check whether value should be state instead
check initial ref value
check when DOM node is available
check cleanup for timers or widgets
check stale closure workarounds
avoid render output based on mutated refs
Interview Framing
Define refs as stable mutable containers. Then contrast refs with state and show DOM focus or timer examples.
Revision Notes
Refs persist across renders and mutation does not re-render. Use them for imperative or non-visual values.
Key Takeaways
Refs are useful precisely because they sit outside normal render updates. That power should be used deliberately.
Follow-Up Questions
- What does useRef return?
- Does changing ref.current re-render?
- When should state be used instead?
- How are DOM refs used?
- What are callback refs?
- How can refs store timer IDs?
- What is a previous value ref?
- Why can refs be escape hatches?
- What cleanup do imperative instances need?
- What changed around initial ref values in React 19 typing?
How I Would Answer This In A Real Interview
I would say useRef gives a stable mutable container. I use it for DOM access, timers, external instances, and values that should persist without re-rendering. If a value affects UI, I use state instead.