What is useRef
and When Should You Use It?
In React, not all data needs to trigger a re-render. That's where useRef
comes in. It allows you to persist mutable values across renders without causing re-renders — and it's also your tool for directly accessing DOM elements.
✅ What is useRef
?
useRef
is a React hook that returns a mutable object with a .current
property.
const ref = useRef(initialValue);
-
The ref.current
value persists across renders.
-
Updating ref.current
does NOT cause the component to re-render.
-
Often used to reference DOM nodes or store imperative values.
🧰 Common Use Cases for useRef
1. Accessing DOM Elements
If you want to manipulate or focus an input element, useRef
gives you direct access.
const inputRef = useRef(null); useEffect(() => { inputRef.current.focus(); // Automatically focus on mount }, []); return <input ref={inputRef} />;
2. Storing Previous Values
Track the previous state or prop without triggering re-renders.
const prevCount = useRef(); useEffect(() => { prevCount.current = count; }, [count]);
3. Avoiding Re-Renders for Mutable Values
Use useRef
to store timers, intervals, or any variable that doesn't affect UI directly.
const timerRef = useRef(null);
4. Preventing Re-Initialization
If you need a value to persist between renders (like a singleton), useRef
helps avoid re-initializing.
const idRef = useRef(generateUniqueId());
❓ useRef
vs useState
: What's the Difference?
Feature |
useState |
useRef |
Triggers re-render |
✅ Yes |
❌ No |
DOM access |
❌ No |
✅ Yes |
Stores values |
✅ Yes |
✅ Yes (without UI sync) |
Common uses |
UI state, logic |
DOM refs, previous values |
⚠️ Gotchas to Avoid
-
Don't use useRef
for reactive state. If the UI depends on a value, use useState
.
-
Be careful with stale refs. Since refs persist, outdated logic inside effects can lead to bugs.
🧩 Pro Tip:
Use useRef
along with useEffect
to track values between renders without causing unnecessary UI updates.
✅ Conclusion
Use useRef
in React when you need to:
-
Access or modify a DOM element directly
-
Store a value that persists across renders but doesn’t affect the UI
-
Avoid performance issues with frequent re-renders
It’s a powerful, lightweight tool—especially when combined with useEffect
or useImperativeHandle
.