Refs with useRef
useRef gives you a mutable reference that persists across renders without triggering re-renders.
Accessing DOM Elements
import { useRef } from "react";
function InputFocus() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} />
<button onClick={focusInput}>Focus</button>
</>
);
}
Pass ref to a DOM element to access it directly.
useRef vs useState
const [count, setCount] = useState(0); // re-renders on change
const countRef = useRef(0); // no re-render on change
Use useRef for values that don’t affect the UI directly.
Persisting Values Across Renders
function Timer() {
const intervalRef = useRef(null);
const start = () => {
intervalRef.current = setInterval(() => {
console.log("tick");
}, 1000);
};
const stop = () => clearInterval(intervalRef.current);
return (
<>
<button onClick={start}>Start</button>
<button onClick={stop}>Stop</button>
</>
);
}
Store timer IDs, previous values, or any mutable data.
When to Use Refs
- Accessing DOM elements (focus, scroll, dimensions)
- Storing timer/animation IDs
- Holding previous values
- Anything that doesn’t need to trigger a re-render
Best Practices
- Don’t use refs for values that should trigger renders
- Access
.currentonly after the element mounts - Use refs sparingly — prefer state for most data
Common Mistakes
- Reading
ref.currentduring render gives stale values - Using refs instead of state for UI-driven data
- Forgetting to initialize refs with
useRef(null)