Part 17: useRef Hook: DOM Access & Persistent Mutable Values
useRef returns a mutable ref object whose .current property is initialized to the passed argument. The returned object persists across renders for the entire lifetime of the component.
1. Two Main Use Cases for useRef
- Accessing DOM nodes directly (focusing inputs, measuring sizes, triggering video playback).
- Storing mutable values that do NOT trigger re-renders when changed.
2. Use Case 1: Direct DOM Manipulation
import { useRef, useEffect } from 'react';
export default function AutoFocusSearch() {
const inputRef = useRef(null);
useEffect(() => {
// Automatically focus the input when the component mounts
inputRef.current.focus();
}, []);
return (
<div className="search-box">
<input
ref={inputRef}
type="text"
placeholder="Type to search..."
className="border p-2 rounded"
/>
</div>
);
}
3. Use Case 2: Persisting Values Without Re-rendering
Changing a ref's .current value does not trigger a component re-render. This is ideal for storing timer IDs, previous prop values, or counters:
import { useState, useRef } from 'react';
export default function Stopwatch() {
const [seconds, setSeconds] = useState(0);
const timerRef = useRef(null);
const startTimer = () => {
if (timerRef.current !== null) return;
timerRef.current = setInterval(() => {
setSeconds(prev => prev + 1);
}, 1000);
};
const stopTimer = () => {
clearInterval(timerRef.current);
timerRef.current = null;
};
return (
<div className="p-4 text-center">
<h2 className="text-3xl font-mono mb-4">{seconds}s</h2>
<div className="flex gap-2 justify-center">
<button onClick={startTimer} className="btn-success">Start</button>
<button onClick={stopTimer} className="btn-danger">Stop</button>
</div>
</div>
);
}
Key Takeaways
useRefprovides a persistent.currentreference across renders.- Updating a ref does not trigger a re-render.
- Use
refto access DOM nodes or store background values like timer IDs.
In Part 18, we will master performance optimization with the useMemo Hook!

