useRef() HookHook DOM Access Mutable Values
The useRef() Hook creates a reference object that can store a mutable value which:
useRef() and has a single property: current.ref.current will not re-render the component.ref attribute.The basic syntax of useRef() looks like this:
// Create a ref with an optional initial value
const myRef = useRef(initialValue);
// Access or update the stored value
myRef.current = 42;
console.log(myRef.current);
myRef.current → The actual value stored (DOM node, number, object, etc.).initialValue → Usually null for DOM elements or a primitive like 0.Use useRef to directly access a DOM element and call methods like focus().
// Focus the input when the button is clicked
import React, { useRef } from "react";
function InputFocus() {
const inputRef = useRef(null);
const handleFocus = () => {
inputRef.current.focus();
};
return (
<div className="text-center">
<input
ref={inputRef}
type="text"
placeholder="Type here..."
className="form-control mb-2"
/>
<button className="btn btn-primary" onClick={handleFocus}>
Focus Input
</button>
</div>
);
}
export default InputFocus;
The page renders an input and a button. When you click “Focus Input”, the cursor jumps into the text box using inputRef.current.focus().
Here, useRef tracks how many times the component has rendered, without causing extra renders.
// Track how many times the component has rendered
function RenderCounter() {
const [count, setCount] = React.useState(0);
const renderCount = React.useRef(0);
React.useEffect(() => {
renderCount.current += 1;
});
return (
<div className="text-center">
<h4>Count: {count}</h4>
<p>Rendered {renderCount.current} times</p>
<button
className="btn btn-success"
onClick={() => setCount(count + 1)}
>
Increment
</button>
</div>
);
}
Each time you click Increment, the count increases and the message updates, showing how many times the component has rendered so far, using renderCount.current.
Use useRef to remember the previous value of a state variable across renders.
// Store the previous value of "count"
function PreviousValue() {
const [count, setCount] = React.useState(0);
const prevCount = React.useRef();
React.useEffect(() => {
prevCount.current = count;
}, [count]);
return (
<div className="text-center">
<h5>Current: {count}</h5>
<h6>Previous: {prevCount.current}</h6>
<button
className="btn btn-primary"
onClick={() => setCount(count + 1)}
>
Increment
</button>
</div>
);
}
The UI shows both the current and previous values of count. Each click updates the current value and shifts the old one into prevCount.current.
useRefStore the timer ID in a ref so it persists across renders and can be started or stopped safely.
// Build a simple timer using a ref for the interval ID
function Timer() {
const [seconds, setSeconds] = React.useState(0);
const timerRef = React.useRef(null);
const startTimer = () => {
if (!timerRef.current) {
timerRef.current = setInterval(() => {
setSeconds((s) => s + 1);
}, 1000);
}
};
const stopTimer = () => {
clearInterval(timerRef.current);
timerRef.current = null;
};
return (
<div className="text-center">
<h5>Time: {seconds}s</h5>
<button
className="btn btn-success me-2"
onClick={startTimer}
>
Start
</button>
<button
className="btn btn-danger"
onClick={stopTimer}
>
Stop
</button>
</div>
);
}
Clicking Start begins a timer that increases every second. Clicking Stop clears the interval using the stored timerRef.current value.
useState vs useRefHow useRef differs from useState:
| Hook | Purpose | Triggers Re-render? |
|---|---|---|
useState |
Stores data that affects rendering | ✅ Yes |
useRef |
Stores mutable values or DOM references | ❌ No |
useRef for values that must persist but shouldn’t re-render the component.useRef with useEffect to track previous values or manage subscriptions.null (e.g., useRef(null)).ref.current will not trigger a re-render—use useState when you need reactivity..current (for example, inputRef.current).useRef to control focus when a button is clicked.useRef to store and clear the interval ID.useRef and useEffect.ref.current in a component and confirm that the UI does not re-render automatically.Goal: Use useRef() to access DOM elements and persist values between renders without triggering re-renders — perfect for timers, inputs, and previous value tracking.