Skip to main content

useRef Hook

useRef = mutable value that persists across renders


What is useRef?

"Mutable ref object"

useRef returns a mutable ref object that persists across renders without causing re-renders.

"useRef returns a mutable ref object that persists across renders, useful for DOM references or storing mutable values that don't trigger re-renders."


Basic Syntax

useRef(initialValue)

const inputRef = useRef(null);

Returns object with .current property.

"useRef takes an initial value and returns a ref object with a current property."


DOM References

Access DOM elements

function Component() {
const inputRef = useRef(null);

const focusInput = () => {
inputRef.current.focus();
};

return (
<>
<input ref={inputRef} />
<button onClick={focusInput}>Focus</button>
</>
);
}

"useRef is commonly used to access DOM elements by passing the ref to the ref prop."


Storing Mutable Values

Values that don't trigger re-renders

function Component() {
const countRef = useRef(0);

const increment = () => {
countRef.current += 1; // No re-render
console.log(countRef.current);
};

return <button onClick={increment}>Count: {countRef.current}</button>;
}

"useRef can store mutable values that persist across renders without causing re-renders when updated."


useRef vs useState

useRef = no re-render, useState = re-render

FeatureuseRefuseState
Re-render on change
Persists across renders
Mutable❌ (immutable)
Use forDOM, timersUI state

"useRef doesn't trigger re-renders when current changes, while useState does. useRef is mutable, useState is immutable."


Common Use Cases

DOM access · Timers · Previous values

  • DOM manipulation: Focus, scroll, measurements
  • Timers: Store interval/timeout IDs
  • Previous values: Track previous props/state
  • Imperative APIs: Third-party library integration

"useRef is used for DOM access, storing timer IDs, tracking previous values, and imperative APIs."


Storing Previous Values

Track previous props/state

function Component({ count }) {
const prevCountRef = useRef();

useEffect(() => {
prevCountRef.current = count;
});

const prevCount = prevCountRef.current;
return (
<div>
Previous: {prevCount}, Current: {count}
</div>
);
}

"useRef can store previous values by updating ref.current in useEffect without dependencies."


Timer Management

Store interval/timeout IDs

function Component() {
const intervalRef = useRef();

useEffect(() => {
intervalRef.current = setInterval(() => {
console.log("Tick");
}, 1000);

return () => clearInterval(intervalRef.current);
}, []);
}

"useRef stores timer IDs for cleanup, preventing memory leaks from intervals or timeouts."


9️⃣ Multiple Refs

Create multiple refs

const input1Ref = useRef(null);
const input2Ref = useRef(null);
const input3Ref = useRef(null);

"Components can use multiple useRef calls for different refs."


Ref Callback Pattern

Function refs for dynamic refs

function Component() {
const [refs, setRefs] = useState([]);

const setRef = (element) => {
if (element) {
setRefs((prev) => [...prev, element]);
}
};

return items.map((item) => (
<div key={item.id} ref={setRef}>
{item.name}
</div>
));
}

"Callback refs allow dynamic ref management, useful for lists or conditional refs."


"useRef returns a mutable ref object that persists across renders without causing re-renders. It's used for DOM references, storing mutable values, timer IDs, and tracking previous values. Unlike useState, updating ref.current doesn't trigger re-renders. Common use cases include DOM manipulation, imperative APIs, and storing values that shouldn't cause re-renders."


🧠 Ultra-Short Cheat Sheet

Mutable ref object
Persists across renders
No re-render on change
DOM references
Store mutable values
Timer IDs
Previous values
useRef vs useState