React useRef Hook
The useRef hook is a powerful tool that allows you to access DOM elements directly and store mutable values that persist across renders without causing re-renders.
This makes useRef ideal for tasks like focusing inputs, tracking previous values, storing timers, or managing any mutable variable in functional components.
What is useRef?
The useRef hook returns a mutable ref object with a .current property:
const refContainer = useRef(initialValue);
refContainer→ an object with a property.current.current→ stores the value or reference- Updating
.currentdoes not trigger a re-render
Importing useRef
import React, { useRef } from "react";
Accessing DOM Elements
One of the most common uses of useRef is to reference a DOM element directly.
Example – Focusing an Input Field:
import React, { useRef } from "react";
function FocusInput() {
const inputRef = useRef(null);
const handleFocus = () => {
inputRef.current.focus(); // Access DOM element
};
return (
<div>
<input ref={inputRef} type="text" placeholder="Type here..." />
<button onClick={handleFocus}>Focus Input</button>
</div>
);
}
export default FocusInput;
ref={inputRef}attaches the ref to the input element.inputRef.current.focus()directly calls the DOM methodfocus().- This avoids using document.querySelector and keeps React in control.
Storing Mutable Values Without Re-rendering
useRef can also store any value that persists across renders:
Example – Tracking Render Count:
import React, { useState, useRef, useEffect } from "react";
function RenderCounter() {
const [count, setCount] = useState(0);
const renderCount = useRef(0);
useEffect(() => {
renderCount.current += 1; // Increment without re-render
});
return (
<div>
<h2>Count: {count}</h2>
<h3>Render Count: {renderCount.current}</h3>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default RenderCounter;
renderCount.currentstores the number of renders.- Updating
.currentdoes not trigger component re-render, unlikeuseState. - Perfect for tracking previous values, timers, or any mutable data.
Combining useRef with useEffect – Previous State
You can use useRef to store the previous state of a component:
import React, { useState, useEffect, useRef } from "react";
function PreviousValueExample() {
const [count, setCount] = useState(0);
const prevCount = useRef(0);
useEffect(() => {
prevCount.current = count; // Store previous value
}, [count]);
return (
<div>
<h2>Current Count: {count}</h2>
<h3>Previous Count: {prevCount.current}</h3>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default PreviousValueExample;
Common useRef Use Cases
- Accessing DOM Elements
- Focusing input fields
- Measuring dimensions
- Scrolling to elements
- Storing Mutable Values
- Previous state
- Timer IDs (
setInterval/setTimeout) - Flags that don’t require re-render
- Integrating with Third-Party Libraries
- Storing references for chart libraries, maps, or custom plugins
Key Points About useRef
.currentcan store any value (DOM element, number, object, etc.)- Updating
.currentdoes not trigger re-render - Ideal for persistent mutable values
- Often used with useEffect for side effects or tracking previous state
Example – useRef with Timer
import React, { useState, useRef, useEffect } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
const intervalRef = useRef(null);
useEffect(() => {
intervalRef.current = setInterval(() => {
setSeconds(s => s + 1);
}, 1000);
return () => clearInterval(intervalRef.current); // Cleanup on unmount
}, []);
return <h2>Seconds: {seconds}</h2>;
}
export default Timer;
