In React, the useRef hook is useful for interacting with the DOM and maintaining values across renders without causing re-renders.
In this post, you’ll learn everything about useRef, including how it works, its use cases, and best practices with examples.
Let’s jump right into it!🚀
What is useRef in React?
useRef is a React Hook that returns a mutable reference object.
This reference persists across renders but does not trigger a re-render when updated. To put it simply, when a component’s state changes, React updates the UI by re-rendering the component. But useRef stores values without triggering this update.
You can think of useRef as a sticky note on your desk. You can update what’s written on it, but it doesn’t affect the layout of your desk. Similarly, useRef stores a value without causing your component to refresh.
Why use useRef in React?
The useRef hook is useful for:
- Accessing and modifying DOM elements directly.
- Storing values between renders without causing re-renders.
- Tracking previous values in a component.
Basic Syntax of useRef
Before using useRef, you need to import it from React:
import { useRef } from "react";
Syntax:
const myRef = useRef(initialValue);
Here,
- useRef(initialValue): Returns an object { current: initialValue }
- The reference persists across renders but does not cause re-renders when updated.
- You can update the value using myRef.current.
For example:
import { useRef } from "react";
function Example() {
const countRef = useRef(0); // Creates a ref with initial value 0
const handleClick = () => {
countRef.current += 1; // Updates ref value (no re-render)
console.log("Current count:", countRef.current);
};
return (
<div>
<button onClick={handleClick}>Increment</button>
</div>
);
}Here,
- countRef is a mutable reference storing a value.
- Clicking the button updates countRef.current, but the UI does not re-render.
- The new value is logged in the console.
Use Case of useRef in React
Use Case 1: Accessing DOM Elements
If you need to access a DOM element directly without using document.querySelector, you can use the useRef hook.
Example: Setting focus on an input field
import { useRef } from "react";
function FocusInput() {
const inputRef = useRef(null); // Create Ref
const handleClick = () => {
inputRef.current.focus(); // This will focus on the input field
};
return (
<div>
<input ref={inputRef} type="text" placeholder="Enter text" />
<button onClick={handleClick}>Focus Input</button>
</div>
);
}
export default FocusInput;In this example,
- useRef(null) creates a reference to store the input element.
- ref={inputRef} connects the reference to the input field.
- inputRef.current.focus() sets focus on the input field when the button is clicked.
Use Case 2: Store Value Without Re-render
If you need to store a value without re-rendering a component, you can use the useRef hook.
Example: Tracking the re-render count
import { useState, useRef, useEffect } from "react";
function RenderCounter() {
const [count, setCount] = useState(0);
const renderCount = useRef(0); // Mutable Value (This will not re-render)
useEffect(() => {
renderCount.current += 1; // Increment render count
});
return (
<div>
<p>Count: {count}</p>
<p>Component Re-rendered: {renderCount.current} times</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default RenderCounter;In this example,
- renderCount persists across renders without causing extra re-renders.
- Using useState instead of useRef here would cause an unnecessary re-render each time renderCount is updated.
Use Case 3: Track the previous value
You can use the useRef hook to store the previous value of a state.
Example:
import { useState, useEffect, useRef } from "react";
function PreviousValueTracker() {
const [count, setCount] = useState(0);
const prevCountRef = useRef(); // This will store previous value
useEffect(() => {
prevCountRef.current = count; // Update Previous Value
}, [count]);
return (
<div>
<p>Current Count: {count}</p>
<p>Previous Count: {prevCountRef.current}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default PreviousValueTracker;Here,
- prevCountRef stores the previous value of count.
- useEffect updates prevCountRef.current whenever count changes.
useRef vs useState: When to use?
| Feature | useRef | useState |
|---|---|---|
| Value Persistence | Yes, persists across renders | Yes, persists across renders |
| Re-render Trigger | No re-render on update | Triggers re-render |
| Use Case | DOM access, previous values | UI updates, state management |
| Initial Value | { current: initialValue } | Any data type supported |
- If you need to update the UI, use the useState hook.
- If you need to store a value without triggering a re-render, use the useRef hook.
Best Practices & Common Mistakes of useRef
Mistake: Using useRef for UI updates
const countRef = useRef(0);
const increment = () => {
countRef.current += 1;
console.log(countRef.current); // This will update the value, but not the UI
};Best Practice: For UI updates, use the useState hook.
Mistake: Using useRef for executing side effects
function App() {
const ref = useRef(0);
if (ref.current === 0) {
console.log("Component mounted!"); // This will execute multiple times
}
ref.current++;
}Here, useRef values persist between renders, but component re-renders don’t reset their value. So the condition (if (ref.current === 0)) will always be true on re-render, causing repeated execution.
Best Practice: Use the useEffect hook for side effects.
Example:
useEffect(() => {
console.log("Component mounted!");
}, []);Why You Need useRef?
- Efficiently access DOM elements.
- Store values across renders without unnecessary re-renders.
- Track previous state values.
That’s all for today!
If you’re new to web development, check out Learnify — my curated platform with beginner-friendly tutorials to help you learn web development step-by-step with examples and simple explanations.
If you enjoy my work and want to support what I do buy me a coffee!
Every small gesture keeps me going! 💛
Follow me on X (Twitter) to get daily web development tips & insights.
Enjoyed reading? You may also find these articles helpful.
14 Essential React Concepts Every Developer Must Know
Top 10 React Component Libraries You Should Know
