
Day 11: Mastering useRef React Hook – Accessing DOM & Persisting Values
In today’s React learning series, we will deep dive into useRef React Hook. When working with React, you’ve probably noticed that most things revolve around state and props. We’ve used useState
to store and update values, and we’ve seen how React automatically re-renders components when state changes.
But what if we want to store a value that doesn’t cause re-renders every time it changes? Or what if we want to directly interact with a DOM element (like focusing an input box)?
That’s where the useRef
hook comes in.
What is useRef?
In simple words:
useRef
is a React hook that lets you create a mutable reference object.- This object has a
.current
property where you can store values. - Unlike state (
useState
), updating.current
does not trigger a re-render.
Think of it like a hidden box in your component—React remembers what’s inside the box, but won’t bother re-rendering the UI when you change its contents.
Syntax
const refContainer = useRef(initialValue);
refContainer
is the object returned byuseRef
.refContainer.current
will hold the actual value.
When to Use useRef?
- Accessing DOM elements directly (like
document.querySelector
in plain JS). - Storing values between renders that don’t need to trigger UI updates.
- Persisting previous values for comparison or debugging.
Example 1: Focusing an Input Field
Let’s say we want a button that automatically focuses on an input field. Normally, we would have to manually grab the element in vanilla JS using document.getElementById
. In React, we can do this cleanly with useRef
.
import React, { useRef } from "react";
function InputFocusExample() {
const inputRef = useRef(null);
const handleFocus = () => {
inputRef.current.focus();
};
return (
<div className="p-4">
<h2 className="text-lg font-bold mb-2">useRef Example: Focus Input</h2>
<input
ref={inputRef}
type="text"
placeholder="Type something..."
className="border p-2 rounded"
/>
<button
onClick={handleFocus}
className="ml-2 px-4 py-2 bg-blue-500 text-white rounded"
>
Focus Input
</button>
</div>
);
}
export default InputFocusExample;
How it works:
- We create
inputRef
withuseRef(null)
. - Assign it to the input element via the
ref
prop. - On button click, we access
inputRef.current
(the actual input element) and call.focus()
.
Example 2: Tracking a Value Without Re-renders
Sometimes you need to store a value but don’t want it to trigger a re-render like useState
would. For example, let’s build a counter that keeps track of clicks but doesn’t re-render the UI every time.
import React, { useRef, useState } from "react";
function CounterWithRef() {
const [renderCount, setRenderCount] = useState(0);
const clickCount = useRef(0);
const handleClick = () => {
clickCount.current += 1;
console.log("Clicked:", clickCount.current);
setRenderCount((prev) => prev + 1);
};
return (
<div className="p-4">
<h2 className="text-lg font-bold mb-2">useRef Example: Counter</h2>
<p>Button clicked: {clickCount.current} times</p>
<button
onClick={handleClick}
className="px-4 py-2 bg-green-500 text-white rounded"
>
Click Me
</button>
<p>Component re-rendered: {renderCount} times</p>
</div>
);
}
export default CounterWithRef;
What’s happening here?
clickCount
is managed byuseRef
, so React doesn’t re-render when it changes.- To see UI changes, we manually update a dummy state
renderCount
. - This shows how
useRef
can store values across renders without causing re-renders.
Difference Between useState and useRef
Feature | useState | useRef |
---|---|---|
Causes re-render? | ✅ Yes | ❌ No |
Stores data across renders? | ✅ Yes | ✅ Yes |
Typical use case | UI updates, dynamic rendering | DOM access, storing values silently |
Why useRef is Important
- It bridges the gap between React world (declarative) and DOM world (imperative).
- It gives you a way to store values that don’t belong to the UI state.
- Without
useRef
, we’d often need hacks or external variables, which break React’s flow.
Wrapping Up
Today we learned:
useRef
is like a box that stores values without triggering re-renders.- You can use it to directly access DOM elements.
- It helps in scenarios where you need to persist values silently between renders.
By now, we’ve covered useState
, useEffect
, and useRef
—three of the most commonly used React hooks.
👉 In the next blog (Day 12), we’ll dive into useReducer, a hook that helps manage complex state logic in a cleaner way than multiple useState
calls.