Loading lessons...
useRef for DOM & Mutable References
useRef for DOM & Mutable References
The useRef hook provides a way to persist mutable values across component re-renders without triggering a re-render when the value changes. It also serves as the primary way to access underlying real DOM nodes in React.
What is a Ref?
Calling useRef(initialValue) returns a plain JavaScript object with a single mutable property: .current.
import { useRef } from 'react';
const myRef = useRef(0);
// Returns object: { current: 0 }
Key Difference: useState vs useRef
| Feature | useState | useRef |
|---|---|---|
| Re-render on change? | ✅ Yes, updates trigger component re-render | ❌ No, updating .current does NOT trigger re-render |
| Access method | State getter variable + setter function | Read & write directly to ref.current |
| Primary Use Cases | Render-affecting data (text, toggles, counters) | DOM element manipulation, timer IDs, previous state |
Use Case 1: Accessing DOM Elements directly
Pass a ref object to a JSX element's ref attribute. React sets ref.current to the corresponding real DOM node once the component mounts.
import { useRef } from 'react';
function SearchInput() {
const inputRef = useRef(null);
const handleFocus = () => {
// Focus real HTML <input> DOM element directly!
inputRef.current.focus();
inputRef.current.style.border = "2px solid blue";
};
return (
<div>
<input ref={inputRef} type="text" placeholder="Click button to focus..." />
<button onClick={handleFocus}>Focus Input</button>
</div>
);
}
Use Case 2: Storing Mutable Variables (e.g. Timer IDs)
function Stopwatch() {
const [seconds, setSeconds] = useState(0);
const timerRef = useRef(null); // Holds interval ID across renders
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>
<h3>Time: {seconds}s</h3>
<button onClick={startTimer}>Start</button>
<button onClick={stopTimer}>Stop</button>
</div>
);
}
Summary & TL;DR
useRef(initialValue)returns a{ current: value }reference object.- Changing
ref.currentdoes NOT trigger component re-renders. - Use
refattributes to access real DOM nodes for focusing, text selection, or media playback.