The useRef()
hook can be used to:
- store mutable value
- access DOM node or React element
function MyComponent() {
const reference = useRef(initialValue);
const someHandler = () => {
// access value
const value = reference.current;
// update value
reference.current = newValue;
};
// ...
}
Update of value should take place in a callback (e.g., one passed to
useEffect()
), not directly in the component.
- updating value does not trigger re-render (unlike state)
- value update is synchronous (unlike state being asynchronous)
- value remains the same on every render
The only difference between
useRef()
and creating a{current: ...}
object yourself is thatuseRef
will give you the same ref object on every render.
function LogButtonClicks() {
const countRef = useRef(0);
const handle = () => {
countRef.current++;
console.log(`Clicked ${countRef.current} times`);
};
return <button onClick={handle}>Click me</button>;
}
function Stopwatch() {
const timerIdRef = useRef(0);
const [count, setCount] = useState(0);
const startHandler = () => {
if (timerIdRef.current) {
return;
}
timerIdRef.current = setInterval(() => setCount(c => c + 1), 1000);
};
const stopHandler = () => {
clearInterval(timerIdRef.current);
timerIdRef.current = 0;
};
useEffect(() => {
return () => clearInterval(timerIdRef.current);
}, []);
return (
<div>
<div>Timer: {count}s</div>
<div>
<button onClick={startHandler}>Start</button>
<button onClick={stopHandler}>Stop</button>
</div>
</div>
);
}
- in event handler
function InputField() {
const inputRef = useRef();
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>
Click to Focus the input
</button>
</div>
);
}
- in the component
function InputFocus() {
const inputRef = useRef();
useEffect(() => {
inputRef.current.focus();
}, []);
return (
<input
ref={inputRef}
type="text"
/>
);
}
Accessing
inputRef.current
outside of a callback will giveundefined
during initial render.
function ClickCounter() {
const counter = useRef(0);
const [, forceUpdate] = useState(Date.now());
function onClick() {
counter.current++;
forceUpdate(Date.now());
}
return (
<div>
{ counter.current }
<button onClick={onClick}>+</button>
</div>
);
}