1. Introduction
When building React applications, you often need to reference DOM elements or store mutable values that persist across renders without triggering re-renders. useRef is a powerful React Hook that addresses these needs. It lets you maintain a stable reference to something that won’t force your component to update when changed—unlike state, which triggers re-renders.
2. Basic Signature
The basic signature for useRef is:
const ref = useRef(initialValue);
- initialValue: The initial value you want to store in the ref’s current property (often null for DOM usage, or a primitive/object for other scenarios).
Returned Value:
- ref: A mutable object with a .current property. React does not manage its updates for rendering—this object remains the same across renders.
3. When to Use useRef
- DOM Manipulation
- Accessing or focusing an input element, measuring a DOM node, or playing/pausing a video element.
- For example, storing a reference to a <div> so you can scroll to it or measure its size.
- Storing Mutable Values
- If you need to preserve data between renders without causing re-renders (e.g., a timer ID, a previous prop value, or a custom counter not tied to the UI).
- Avoiding Re-render Loops
- useRef is ideal for data you don’t want to trigger a re-render each time it changes (unlike state which triggers UI updates).
- Integration with External Libraries
- Some non-React or third-party code may require direct references to DOM nodes or mutable objects. useRef helps unify that approach.
4. Basic Example: DOM Access
A common use case is focusing an input element on mount or at the click of a button:
import React, { useRef, useEffect } from "react";
export default function TextInputFocus() {
const inputRef = useRef(null);
useEffect(() => {
// Focus the input on mount
inputRef.current.focus();
}, []);
return (
<div>
<input ref={inputRef} type="text" placeholder="Focus on me automatically" />
</div>
);
}
Explanation
- useRef(null): Creates a ref object with an initial .current value of null.
- inputRef.current: Points to the actual <input> DOM element after the component mounts.
- useEffect: Focuses the input once the DOM node is available.
5. Storing Mutable Values
Aside from DOM elements, useRef can store any mutable data. For instance, you might want to track the previous value of a prop or store a timer ID without re-rendering:
import React, { useState, useRef } from "react";
export default function TimerComponent() {
const [count, setCount] = useState(0);
const timerIdRef = useRef(null);
function startTimer() {
if (timerIdRef.current) return; // Already running
timerIdRef.current = setInterval(() => {
setCount((prev) => prev + 1);
}, 1000);
}
function stopTimer() {
clearInterval(timerIdRef.current);
timerIdRef.current = null;
}
return (
<div>
<p>Count: {count}</p>
<button onClick={startTimer}>Start</button>
<button onClick={stopTimer}>Stop</button>
</div>
);
}
Explanation
- timerIdRef: Holds the ID returned by setInterval, preventing multiple intervals from spawning.
- This value can be changed without forcing the component to re-render.
6. Best Practices & Tips
- Initialize to null for DOM
- For DOM usage, useRef(null) is common to start with no element until the component mounts.
- Remember .current
- The actual value or DOM node is in ref.current. Setting ref.current = ... changes it, but won’t cause re-render.
- Don’t Abuse Refs
- If you need the UI to update when a value changes, don’t store it in a ref—use state instead.
- Refs are great for “behind the scenes” data.
- Avoid Layout Thrashing
- If measuring DOM nodes or performing animations, consider useLayoutEffect to ensure measurements happen before the screen repaints.
- External Libraries
- Refs can simplify integrations with libraries that need direct DOM references (like certain charting or map libraries).
7. Common Pitfalls
- Forgetting the .current Property
- Doing console.log(ref) might just show the object wrapper. You need ref.current to access the underlying DOM or data.
- Uncontrolled vs. Controlled Components
- Using a ref for form inputs bypasses React’s controlled pattern. Ensure it’s deliberate if you store input values in a ref.
- useRef Is Not for Triggering UI Updates
- If you want the UI to reflect changes, store them in state. useRef doesn’t re-render.
- Memory Leaks
- If you store large data or subscription references in a ref, remember to clean up or consider how long the ref persists.
8. Example: Scroll to Element
Another popular ref pattern is scrolling to a specific section:
import React, { useRef } from "react";
export default function ScrollExample() {
const sectionRef = useRef(null);
function scrollToSection() {
sectionRef.current.scrollIntoView({ behavior: "smooth" });
}
return (
<div>
<button onClick={scrollToSection}>Scroll to Section</button>
<div style={{ height: "1200px" }}>Some long content above...</div>
<div ref={sectionRef} style={{ background: "lightblue", padding: "20px" }}>
Target Section
</div>
</div>
);
}
Key Points
- sectionRef.current.scrollIntoView() smoothly scrolls the user to the target section.
- The user doesn’t see the ref, but the code can manipulate the DOM as needed.
9. Conclusion
useRef in React 19 remains an essential hook for direct DOM manipulations or storing mutable data that doesn’t affect rendering. By following the basic signature:
const ref = useRef(initialValue);
you gain a stable reference that persists across re-renders, allowing you to focus elements, store IDs, or integrate external libraries without accidentally forcing your component to update.
Key Takeaways
- DOM Access: Attach refs to elements with <div ref={myRef} />.
- Mutable Values: Great for caching data between renders without re-render overhead.
- ref.current: Always check or modify the .current property.
- No Re-renders: Changes to refs do not trigger re-render—use state if you need UI updates.
With these insights, you can confidently leverage useRef to handle behind-the-scenes logic or DOM tasks in your React 19 projects, keeping your code both clean and performant.
'Dev > React' 카테고리의 다른 글
A Practical Guide to useSyncExternalStore in React 19 (0) | 2025.03.09 |
---|---|
A Practical Guide to useState in React 19 (0) | 2025.03.09 |
A Practical Guide to useReducer in React 19 (0) | 2025.03.09 |
A Practical Guide to useOptimistic in React 19 (0) | 2025.03.09 |
A Practical Guide to useMemo in React 19 (0) | 2025.03.08 |