What is the useRef hook in React?
useRef returns a mutable ref object that persists across renders without causing re-renders - used for accessing DOM nodes and storing mutable values.
React
Overview
`useRef` creates a plain mutable container (`{ current: ... }`) that persists across renders. Unlike `useState`, changing `ref.current` does **not** trigger a re-render. It has two main use cases: accessing DOM elements directly, and storing any mutable value you want to "remember" without causing a re-render.
Key Points
- •`const ref = useRef(initialValue)` - `ref.current` holds the value.
- •Pass `ref` to a JSX element's `ref` prop to get the DOM node in `ref.current`.
- •Changing `ref.current` does not cause a re-render.
- •A ref is like an instance variable in a class component - mutable, persistent, invisible to React.
- •Common uses: focus management, animations, storing previous values, holding timer IDs.
Examples
Accessing a DOM element
tsximport { useRef, useEffect } from 'react';
function SearchInput() {
const inputRef = useRef<HTMLInputElement>(null);
// Auto-focus on mount
useEffect(() => {
inputRef.current?.focus();
}, []);
return <input ref={inputRef} placeholder="Search..." />;
}Store a mutable value without triggering re-renders
tsxfunction StopwatchTimer() {
const [time, setTime] = useState(0);
const intervalRef = useRef<number | null>(null);
const start = () => {
intervalRef.current = setInterval(() => {
setTime(t => t + 1);
}, 1000);
};
const stop = () => {
clearInterval(intervalRef.current!);
intervalRef.current = null;
};
return <button onClick={intervalRef.current ? stop : start}>Toggle</button>;
}The interval ID is stored in a ref - it does not need to live in state because we never render it.
Track the previous value of a state
tsxfunction usePrevious<T>(value: T): T | undefined {
const ref = useRef<T | undefined>(undefined);
useEffect(() => {
ref.current = value; // stores current value after render
});
return ref.current; // returns previous value (before this render)
}
function Counter() {
const [count, setCount] = useState(0);
const prev = usePrevious(count);
return <p>Now: {count}, Before: {prev}</p>;
}Pro Tip
If you find yourself reaching for `useRef` to store something that the UI needs to display, you probably want `useState` instead. `useRef` is for values that need to persist across renders but should NOT drive the UI.