The useRef hook in React is used to directly reference DOM elements or persist mutable values without causing re-renders. It is an incredibly useful tool for scenarios where you need to interact with the DOM or retain a mutable state across renders.
When to Use useRef
- Accessing DOM Elements: Directly manipulate or access a DOM element (e.g., focusing an input, scrolling).
- Storing Mutable Data: Retain values (like timers, IDs, or previous states) without triggering re-renders.
- Keeping Previous Values: Store the previous value of props or state for comparison.
Syntax
const refContainer = useRef(initialValue);
refContainer: An object with acurrentproperty where the value is stored.initialValue: The initial value to be assigned to thecurrentproperty.
Example 1: Accessing a DOM Element
Code Example: Focus on an Input Field
import React, { useRef } from "react";
function FocusInput() {
const inputRef = useRef(null);
const handleFocus = () => {
inputRef.current.focus(); // Focus the input field
};
return (
<div>
<input type="text" ref={inputRef} placeholder="Enter text" />
<button onClick={handleFocus}>Focus Input</button>
</div>
);
}
export default FocusInput;
- Explanation:
useRefcreates a reference to the input element.- The
currentproperty of the reference is used to call thefocusmethod.
Example 2: Persisting Mutable Values
Code Example: Store Timer Value
import React, { useRef, useState } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
const timerRef = useRef(null);
const startTimer = () => {
if (!timerRef.current) {
timerRef.current = setInterval(() => {
setSeconds((prev) => prev + 1);
}, 1000);
}
};
const stopTimer = () => {
clearInterval(timerRef.current);
timerRef.current = null;
};
return (
<div>
<p>Timer: {seconds} seconds</p>
<button onClick={startTimer}>Start</button>
<button onClick={stopTimer}>Stop</button>
</div>
);
}
export default Timer;
- Explanation:
timerRefholds the timer ID.- Since
useRefdoesn’t trigger re-renders, the timer logic remains efficient.
Example 3: Storing Previous State
Code Example: Previous Value Comparison
import React, { useRef, useEffect, useState } from "react";
function PreviousValueExample() {
const [count, setCount] = useState(0);
const prevCount = useRef(null);
useEffect(() => {
prevCount.current = count; // Update the previous value
});
return (
<div>
<p>Current Count: {count}</p>
<p>Previous Count: {prevCount.current}</p>
<button onClick={() => setCount((prev) => prev + 1)}>Increment</button>
</div>
);
}
export default PreviousValueExample;
- Explanation:
- The
prevCountref stores the count value from the previous render. - It doesn’t cause a re-render when updated.
- The
Example 4: Managing Animations
Code Example: Smooth Scrolling
import React, { useRef } from "react";
function SmoothScroll() {
const divRef = useRef(null);
const scrollToBottom = () => {
divRef.current.scrollIntoView({ behavior: "smooth" });
};
return (
<div>
<div style={{ height: "500px", overflow: "auto", border: "1px solid black" }}>
<div style={{ height: "1000px" }}>Scroll Down</div>
<div ref={divRef}>You’ve reached the bottom!</div>
</div>
<button onClick={scrollToBottom}>Scroll to Bottom</button>
</div>
);
}
export default SmoothScroll;
- Explanation:
useReftargets a specific DOM element.- The
scrollIntoViewmethod is triggered for smooth scrolling.
Key Points About useRef
- Does Not Trigger Re-Renders: Updating the
.currentproperty doesn’t re-render the component. - Persistent Across Renders: The value persists between renders, unlike local variables inside the function.
- Avoid Overuse: Use
useRefprimarily for DOM manipulation or storing non-reactive data.
Common Mistakes with useRef
- Misusing for State: Don’t use
useReffor values that need to trigger re-renders. UseuseStateinstead. - Unnecessary Updates: Avoid frequent updates to
currentwhen it isn’t necessary. - Improper Initial Value: Ensure the
initialValuematches the type of data you plan to store.
Best Practices
- Use
useReffor accessing or modifying DOM elements directly. - Combine with
useEffectfor side effects that involve the DOM. - For better readability, encapsulate logic involving
useRefin custom hooks when reused frequently.
useRef is a lightweight and powerful tool for managing mutable references, making it invaluable for specific scenarios in React development.