JAVASCRIPT
Interact with DOM and Store Mutable Values with useRef
Learn to use React's useRef hook for direct DOM manipulation, accessing elements, or storing mutable values that persist across renders without triggering updates.
import React, { useRef, useEffect, useState } from 'react';
function MyRefComponent() {
const inputRef = useRef(null);
const countRef = useRef(0); // For a persistent mutable value
const [_, setRerender] = useState(0); // To force a re-render for countRef demo
useEffect(() => {
// Focus the input field when the component mounts
if (inputRef.current) {
inputRef.current.focus();
}
}, []); // Empty dependency array means this runs once on mount
const handleClick = () => {
// Accessing and manipulating DOM directly
if (inputRef.current) {
alert(`Input value: ${inputRef.current.value}`);
inputRef.current.value = 'Hello useRef!';
}
};
const incrementCountRef = () => {
countRef.current = countRef.current + 1;
console.log('countRef.current:', countRef.current);
// Note: Updating a ref does NOT trigger a re-render.
// To display the updated value, you'd need a state update.
setRerender(prev => prev + 1); // Force re-render to display latest countRef.current
};
return (
<div>
<h2>useRef Example</h2>
<input type="text" ref={inputRef} placeholder="Focus me on load" />
<button onClick={handleClick}>Get Input Value & Change</button>
<h3>Persistent Value with useRef</h3>
<p>Count Ref Value (does not trigger re-render on its own): {countRef.current}</p>
<button onClick={incrementCountRef}>Increment Count Ref</button>
<p>Clicking "Increment Count Ref" updates the ref, but for it to display, a state update (like the dummy state here) is needed to trigger a re-render. `countRef.current` itself is persistent across renders.</p>
</div>
);
}
export default MyRefComponent;
How it works: The `useRef` hook returns a mutable ref object whose `.current` property is initialized to the passed argument (`initialValue`). The returned object will persist for the full lifetime of the component. It's commonly used for direct DOM access (e.g., `inputRef.current.focus()`) or to store any mutable value that doesn't need to trigger a re-render when it changes, like a counter that persists across renders (`countRef.current`).