useRef
useRef
useRef is a React Hook that lets you reference a value that’s not needed for rendering. It provides a way to persistently store mutable values across renders without causing a component to re-render when the value changes.
Syntax
import { useRef } from 'react';
const ref = useRef(initialValue);
useRef returns an object with a single property:
current: Initially set to theinitialValueyou passed. You can later read or write to this property.
Primary Use Case 1: Manipulating the DOM
The most common use case for useRef is to directly access a DOM element to call imperative APIs (like .focus(), .play(), or .scrollIntoView()).
To do this, you create a ref and pass it to the ref attribute of a JSX element. React will assign the DOM node to ref.current.
function TextInputWithFocusButton() {
// 1. Create the ref
const inputEl = useRef(null);
const onButtonClick = () => {
// 3. Use the ref to interact with the DOM node directly
inputEl.current.focus();
};
return (
<>
{/* 2. Attach the ref to the element */}
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
Primary Use Case 2: Storing Mutable Values
You can also use a ref to store any value that you want to persist between renders, but that doesn’t affect the visual output of the component.
For example, tracking a timer ID so you can clear it later:
function Timer() {
const [count, setCount] = useState(0);
// Store the interval ID in a ref so it doesn't trigger re-renders when set
const timerIdRef = useRef(null);
const start = () => {
timerIdRef.current = setInterval(() => setCount(c => c + 1), 1000);
};
const stop = () => {
clearInterval(timerIdRef.current);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={start}>Start</button>
<button onClick={stop}>Stop</button>
</div>
);
}
Differences between useRef and useState
| Feature | useRef | useState |
|---|---|---|
| Does it trigger a re-render? | No. Mutating .current does not re-render. | Yes. Calling the state setter triggers a re-render. |
| Is the value mutable? | Yes. You can modify .current directly. | No. You must use the state setter function. |
| When to use? | Values that don’t affect the UI (timers, DOM nodes). | Values that directly affect what is rendered on screen. |
Interview Questions
Q: What are the two primary use cases for useRef?
A:
- Accessing native DOM elements directly (e.g., calling
.focus()on an input). - Storing mutable values (like timers, intervals, or previous state) that persist across renders without triggering a re-render when they are updated.
Q: If you update a useRef value (ref.current = 10), will the component update on the screen?
A: No. Changing a ref does not trigger a re-render. This makes it perfect for tracking background data, but terrible for tracking data that needs to be displayed in the UI.