useRef
useRef holds a mutable value or a reference to a DOM node without re-rendering.
Syntax
const inputRef = useRef(null);useRef returns a mutable object with a .current property. Changing .current does not trigger a re-render, which makes refs useful for two things.
Common uses
- DOM access — attach a ref to an element to focus it, measure it, or play media.
- Persisting a value across renders without causing re-renders, like a timer id or previous value.
Example
import { useRef } from 'react';
function SearchBox() {
const inputRef = useRef(null);
function focusInput() {
inputRef.current.focus();
}
return (
<div>
<input ref={inputRef} placeholder="Search..." />
<button onClick={focusInput}>Focus</button>
</div>
);
}When to use it
- An auto-focus field uses useRef to call .focus() on an input element the moment a modal opens, without the user needing to click.
- A video player component holds a ref to the <video> element so imperative play/pause methods can be called from a custom control bar.
- A debounce hook stores the timer ID in a ref so it persists across re-renders without triggering extra renders when the timer is reset.
More examples
Focus an input on mount
Attaches a ref to an input element and calls focus() after mount without causing any extra renders.
import { useRef, useEffect } from 'react';
function AutoFocusInput() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
return <input ref={inputRef} placeholder="Start typing..." />;
}Store mutable value without re-render
Stores the interval ID in a ref so it persists across renders without triggering them when updated.
import { useState, useRef } from 'react';
function StopWatch() {
const [elapsed, setElapsed] = useState(0);
const intervalRef = useRef(null);
const start = () => {
intervalRef.current = setInterval(
() => setElapsed(e => e + 1), 1000
);
};
const stop = () => clearInterval(intervalRef.current);
return (
<div>
<p>{elapsed}s</p>
<button onClick={start}>Start</button>
<button onClick={stop}>Stop</button>
</div>
);
}Track previous prop value
Uses a ref updated in useEffect to remember the value from the previous render for comparison.
import { useRef, useEffect } from 'react';
function usePrevious(value) {
const ref = useRef(undefined);
useEffect(() => { ref.current = value; });
return ref.current;
}
function PriceDisplay({ price }) {
const prevPrice = usePrevious(price);
const direction = price > prevPrice ? 'up' : 'down';
return <p className={direction}>${price}</p>;
}
Discussion