
React useRef Hook Explained with Real Examples and Best Practices (2025 Guide)
- bilalshafqat42
- June 24, 2025
- React Js, React Hooks
- 0 Comments
Learn what the React useRef()
hook does, when to use it, and how it compares to useState()
. Includes real-world examples for DOM access, value tracking, and performance optimizations.
Introduction: What is useRef in React?
If you’re working with React functional components, you’ve probably used useState()
and useEffect()
— but what about useRef()
?
React’s useRef()
hook is a powerful yet often underutilized tool. While it’s commonly associated with accessing DOM elements, it’s much more versatile than that.
In this guide, you’ll learn:
- What
useRef()
is - When and why to use it
- How it differs from
useState()
- Real examples including DOM access, persisting values, and timers
- Common mistakes to avoid
- Best practices for 2025 and beyond
What is useRef?
useRef()
is a built-in React hook that returns a mutable object with a .current
property. Unlike state, updating this .current
value does not trigger a re-render.
Syntax:
const ref = useRef(initialValue);
What it returns:
{
current: initialValue
}
This ref object persists for the entire lifetime of the component.
When to Use useRef()
1. Accessing DOM Elements
This is the most well-known use case — directly referencing a DOM node for actions like focusing an input or scrolling.
2. Persisting Values Across Renders
You can store a value in a ref that will survive re-renders without causing the component to update.
3. Storing Previous Props or State
Refs are perfect for tracking what a value was during the previous render — without triggering another render.
4. Timer IDs or Animation References
If you’re using setTimeout
, setInterval
, or animations, useRef()
lets you store IDs cleanly.
Example 1: Focus an Input Field
import { useRef } from 'react';
function FocusInput() {
const inputRef = useRef();
return (
<>
<input ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>
Focus Input
</button>
</>
);
}
In this example:
useRef()
creates a reference object.- React assigns that object to the
ref
attribute. - On button click, you call
.focus()
on the DOM node.
Example 2: Tracking Previous State
import { useEffect, useRef, useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const prevCount = useRef();
useEffect(() => {
prevCount.current = count;
}, [count]);
return (
<>
<p>Current: {count}</p>
<p>Previous: {prevCount.current}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</>
);
}
This setup tracks the previous count value without triggering any extra renders.
useRef vs useState: What’s the Difference?
Feature | useRef | useState |
---|---|---|
Triggers re-render | No | Yes |
Persists across renders | Yes | Yes |
DOM access | Yes | No |
UI state updates | No | Yes |
Use for | DOM, timers, previous values | User-facing state |
Common Mistakes to Avoid with useRef
Mistake 1: Using ref for data that should trigger a re-render
If your UI depends on a value, it should be stored in state — not ref.
Bad:
const countRef = useRef(0);
countRef.current += 1;
Better:
const [count, setCount] = useState(0);
setCount(count + 1);
Mistake 2: Forgetting that useRef doesn’t cause a re-render
Changing .current
won’t make the component update. This is both a feature and a gotcha.
Mistake 3: Assuming useRef is only for DOM
Refs can hold anything — not just DOM elements. Think of it as a safe, persistent container.
Best Practices for useRef in 2025
- Use it to hold mutable values you don’t want to trigger a render
- Use it to reference DOM nodes for animations or focus behavior
- Combine with
useEffect()
to track previous props or state - Use it to store timers or animation frame IDs
- Avoid overusing it where
useState()
oruseReducer()
are better fits
Real-World Use Cases
Accessing a scrollable container:
const scrollRef = useRef();
scrollRef.current.scrollTop = 0;
Controlling a video player:
videoRef.current.play();
Tracking if component is mounted:
const isMounted = useRef(false);
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);
Should I Use useRef or useMemo?
useRef()
is for storing mutable values, like DOM nodes or internal variables.
useMemo()
is for memoizing computed values to prevent unnecessary recalculations.
Use useRef
when:
- You need to store a DOM node
- You need a stable reference that persists between renders
- You’re tracking internal mutable state that doesn’t affect UI
Use useMemo
when:
- You’re calculating a value that should be cached
- You want to optimize expensive logic that runs every render
Summary: useRef() in React
useRef()
is a flexible, persistent container inside your component. It’s ideal for:
- Managing focus and scrolling
- Tracking previous values
- Holding timers or animation IDs
- Avoiding unnecessary re-renders
Just remember: useRef()
is not reactive — changing .current
does not trigger re-renders.
Use it for logic and side effects, not for data that needs to appear in the UI.
Learn More
Want to dive deeper into hooks like useState
, useEffect
, and useContext
?