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.
Before we get started, don’t forget to subscribe to my newsletter!
Get the latest tips, tools, and resources to level up your web development skills delivered straight to your inbox. Subscribe here!
Now let’s jump right into it!🚀
What is useRef?
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?
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
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.
🎯Wrapping Up
That’s all for today!
I hope this post helps you.
If you found this post helpful, here’s how you can support my work:
☕ Buy me a coffee – Every little contribution keeps me motivated!
📩 Subscribe to my newsletter – Get the latest tech tips, tools & resources.
𝕏 Follow me on X (Twitter) – I share daily web development tips & insights.
Keep coding & happy learning!