Hooks Deep Dive
The rest of React's built-in hooks - useRef, useReducer, useId, and the rules that govern how all hooks work together.
What it is, in plain English: Beyond useState and useEffect, React provides several more built-in hooks for specific jobs: useRef holds a mutable value that persists across renders without triggering re-renders (often used for DOM references). useReducer manages complex state logic with multiple sub-values via a reducer function, similar to Redux. useId generates unique IDs for accessibility attributes. Understanding these fills out the complete hooks toolkit for building real applications.
useRef -- a box that doesn't trigger re-renders
useState causes a re-render every time you update it. Sometimes you need to
remember a value across renders WITHOUT causing a re-render -- that's what
useRef is for.
The most common use -- accessing a DOM element
function TextInputWithFocusButton() {
const inputRef = React.useRef(null);
function handleClick() {
inputRef.current.focus(); // .current gives you the actual DOM node
}
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>Focus the input</button>
</>
);
}
// React sets inputRef.current to the real <input> DOM element after it mounts.
// This is the standard way to call DOM methods (focus, scrollIntoView, play, etc.)
// that React doesn't have a declarative prop for.useRef for storing any mutable value
function StopwatchTimer() {
const [elapsed, setElapsed] = React.useState(0);
const intervalRef = React.useRef(null); // stores the interval ID
function start() {
intervalRef.current = setInterval(() => {
setElapsed(e => e + 1);
}, 1000);
}
function stop() {
clearInterval(intervalRef.current); // read the stored ID to clear it
}
return (
<div>
<p>{elapsed}s</p>
<button onClick={start}>Start</button>
<button onClick={stop}>Stop</button>
</div>
);
}
// Key difference from useState: changing intervalRef.current does NOT
// cause a re-render. useRef is for values the component needs to remember
// but that should never directly cause the UI to update.The Rules of Hooks, restated clearly
// 1. Only call hooks at the TOP LEVEL of a component or custom hook
// (never inside if/for/while/nested functions)
// 2. Only call hooks from React function components or custom hooks
// (never from regular JS functions or class components)
function GoodComponent() {
const [a, setA] = React.useState(0); // ✓ top level
const ref = React.useRef(null); // ✓ top level
React.useEffect(() => {}, []); // ✓ top level
if (a > 5) {
// const [b] = React.useState(0); // ✗ would break the rules
}
}
Try It Yourself (JSX)
Official Sources
- React Documentation — Referencing Values with Refs
- React Documentation — Manipulating the DOM with Refs
- React Documentation — Extracting State Logic into a Reducer
- React Documentation — useReducer Reference
- React Documentation — useId Reference
The Codex links only to official documentation. No third-party tutorials.