B. React Hooks Quick Reference

Every hook in the stable API of React 19.3, released on 9 September 2026, plus the one hook that lives in react-dom. The fourth column says what makes the hook do its work again — a re-render, a re-run of a setup function, or nothing at all — and the fifth is the mistake that shows up most often in code review. All of them obey the same two rules: call them at the top level of a component or another hook, and call them in the same order on every render. use is the single exception, and the last table says what the React Compiler does to the rest. Hook Signature Returns Re-runs on Commonest mistake § useState useState(initial) [state, setState] A setState with a value Object.is says is new Reading state right after setting it 2.3.1 useState (lazy) useState(() => make()) same Initializer runs on the first render only Passing make(), which runs every render 2.3.5 useState (updater) setState(prev => next) same Queues against the latest value, not this render's Batching repeated setState(count + 1) calls 2.3.3 useReducer useReducer(fn, arg, init?) [state, dispatch] A dispatch whose reducer returns a new object Mutating state inside the reducer 2.5.6 useReducer (lazy) useReducer(fn, arg, init) same init(arg) runs on the first render only Rebuilding the initial state on every render 2.5.7 useContext useContext(Ctx) Nearest provider's value The provider's value changes identity A fresh object literal as value each render 2.5.2 useRef useRef(initial) { current }, stable Never; writing current re-renders nothing Reading current during render 2.6.1 useRef (callback) ref={node => cleanup} React 19 runs the returned cleanup On attach and again on detach Returning anything but a cleanup function 2.6.4 useImperativeHandle useImperativeHandle(ref, create, deps?) Nothing deps change, after DOM commit Exposing the node instead of a small API 2.6.8 Table B.1: State, context and ref hooks Effects run after React has committed to the DOM. Which one you pick decides where in that commit you land: after the browser paints, before it paints, or before the styles are even inserted. Hook Signature Returns Re-runs on Commonest mistake § useEffect useEffect(setup, deps?) Nothing After paint, when a dep changes identity Omitting the cleanup, so subscriptions stack up 2.4.1 useEffect (deps) deps omitted, [], or listed Nothing Every render, once, or on change Silencing the lint rule instead of fixing deps 2.4.2 useEffect (cleanup) return () => stop() Nothing Before the next setup and on unmount Letting a slow response overwrite a newer one 2.4.5 useLayoutEffect useLayoutEffect(setup, deps?) Nothing Before paint, blocking it Measuring layout work that useEffect could do 2.4.8 useInsertionEffect useInsertionEffect(setup, deps?) Nothing Before any DOM mutation Using it outside a CSS-in-JS library — useEffectEvent useEffectEvent(fn) A stable, non-reactive function Never; it always sees the latest props Listing it in a dependency array 2.4.7 Table B.2: Effect hooks Concurrency hooks let React keep an old screen interactive while a new one renders. use is the odd one out: it may be called inside a condition or a loop, but never inside try. Hook Signature Returns Re-runs on Commonest mistake § useMemo useMemo(calc, deps) Cached value A dep changes identity Memoizing arithmetic that costs less than the check 2.7.3 useCallback useCallback(fn, deps) Cached function A dep changes identity Using it on a child that is not wrapped in memo 2.7.4 useTransition useTransition() [isPending, startTransition] Marks its updates low-priority Wrapping an input's own value update 2.8.2 useDeferredValue useDeferredValue(value, initial?) A lagging copy of value Re-renders again once the urgent work lands Deferring a value that is cheap to render 2.8.4 use use(promise) The resolved value Suspends until the promise settles Creating the promise during render 2.8.6 use (context) use(Ctx), legal inside if The context value Same conditions as useContext Reaching for it inside a try block 2.8.6 useSyncExternalStore useSyncExternalStore(sub, get, getServer?) The current snapshot The store calls the subscriber Returning a new object from getSnapshot 2.8.8 Table B.3: Performance and concurrent rendering hooks Form hooks connect a component to an action — the async function a <form action={...}> or formAction runs. useFormStatus is imported from react-dom, not react, and reads the form above it. Hook Signature Returns Re-runs on Commonest mistake § useActionState useActionState(action, initial, url?) [state, formAction, isPending] The action returns a new state Forgetting the action's first argument is prior state 2.9.3 useFormStatus useFormStatus() { pending, data, method, action } The enclosing form starts or ends a submit Calling it in the component that renders <form> 2.9.4 useOptimistic useOptimistic(value, reducer?) [optimistic, addOptimistic] Reverts when the action settles Calling addOptimistic outside a transition 2.9.5 useId useId() A stable string, unique per instance Never changes for a given component Using it as a list key 2.8.7 useDebugValue useDebugValue(value, format?) Nothing Read by React DevTools only Calling it in a component instead of a custom hook 2.10.10 Table B.4: Form, identity and debugging hooks The React Compiler, stable since version 1.0, inserts memoization at build time. Where it runs, hand-written memoization is dead weight; where it cannot see, you still write it yourself. Written by hand What the compiler does instead Still write it when § useMemo for a derived value Caches the expression and its inputs automatically The value is used by non-React code, or caching is semantic 2.7.7 useCallback for a stable prop Gives every closure a stable identity The identity is compared by addEventListener or a library 2.7.7 memo(Component) Skips re-rendering unchanged subtrees on its own The child ships pre-compiled from node_modules 2.7.2 useRef to dodge a re-render Nothing; refs are not memoization Always — the compiler does not replace refs 2.6.1 Dependency arrays Nothing; effect deps stay your responsibility Always — only memoization is automated 2.4.2 Opting out Honors a "use no memo" directive in a file A component breaks under auto-memoization 2.7.8 Table B.5: Hooks the React Compiler makes unnecessary Warning: useFormState from React 18's canary builds was renamed useActionState and moved from react-dom to react. Old tutorials still import the former; it is gone from React 19. Hooks are ordinary functions with one unusual requirement: React identifies them by call order, not by name. Everything in the next table follows from that, and eslint-plugin-react-hooks catches all six. Rule What breaks if you ignore it How it shows up § Call hooks at the top level State attaches to the wrong slot "Rendered fewer hooks than expected" 2.10.2 Never call a hook in a condition or loop The order changes between renders State from one field appears in another 2.10.2 Call hooks only from components or hooks React has no render to attach to "Invalid hook call" from a plain function 2.10.2 Name custom hooks useSomething The linter stops checking the file Missing dependencies go unreported 2.10.1 Keep render pure Concurrent rendering may run it twice Doubled writes under Strict Mode 2.11.8 List every reactive value in deps Effects read stale props and state A fetch keeps using yesterday's id 2.4.2 Table B.6: The rules of hooks and what each one prevents

// Wrong: the hook count changes with the prop

if (props.editable) { const [text, setText] = useState(''); }

// Right: call it always, branch on the result

const [text, setText] = useState('');

Listing B.1: The one rule everything else follows from Custom hooks are how you package the rules once and reuse them. These are the ones built in Section 2.10; each returns plain values, so nothing stops you from composing them inside another hook. Custom hook Returns Built on § usePrevious(value) The value from the previous render useRef plus useEffect 2.10.3 useFetch(url) { data, error, loading } useEffect with an AbortController 2.10.4 useWindowSize() { width, height } A resize listener in useEffect 2.10.5 useOutsideAlerter(ref, fn) Nothing; calls fn on outside clicks A document listener plus a ref 2.10.6 useScript(src) 'loading', 'ready' or 'error' An injected <script> in useEffect 2.10.7 useDebounce(value, ms) The value, settled after ms useState plus a cleared timer 2.10.8 useLocalStorage(key, initial) [value, setValue], persisted useState with lazy initialization 2.10.9 Table B.7: The custom hooks built in this book