React 19 Hooks Cheat Sheet
React 19 on one page: Actions and useTransition, useOptimistic, use(), useDeferredValue, useEffectEvent, refs as props, and the React Compiler's automatic memoisation.
Growingtended planted 2 min read
React 19 turns async UI into first-class primitives (Actions, useTransition, useOptimistic, use), and the
React Compiler memoises for you, so most hand-written useMemo and useCallback becomes optional.
The headline features
- Actions. Async functions passed to a transition or a form get pending state, optimistic updates, error handling
and form reset handled for you (
<form action={fn}>,useActionState). - Refs are just props. No more
forwardRefto pass a ref down. - The React Compiler memoises functions, values and components at build time. React DevTools and editor extensions show which components it memoised.
- Server Components render ahead of time on the server; see Front-end Rendering Strategies and Architecture.
The hooks
| Hook | What it’s for | Remember |
|---|---|---|
useTransition | Mark an update as non-urgent; get isPending for feedback | Update-level deferral. In React 19 it accepts async functions (Actions) |
useDeferredValue | Let a value lag behind urgent renders | Value-level deferral: render the stale value first, then the new one. Good for filtered lists and fresh responses without a loading flicker |
useOptimistic | Show the final state while the request is in flight | Fast feedback at the cost of consistency; reverts if the action fails |
use | Read a promise or context during render (can be conditional) | Suspends on promises; rejections go to the nearest error boundary (React Error Handling) |
useEffectEvent | Pull event logic out of an effect | A stable function that always sees the latest props and state, so effects stop re-running because a callback changed |
useRef | A value that isn’t needed for rendering | Always current, never triggers a re-render |
useId | Stable unique IDs | For accessibility (<label htmlFor>, aria-*), not for list keys |
useDebugValue | Label custom hooks in DevTools | Nicer debugging |
useTransition or useDeferredValue? Same idea, different handle. Use the transition when you own the state
setter; use the deferred value when you only receive the value, for example as a prop.
Optimistic updates with an Action
const [optimisticTodos, addOptimistic] = useOptimistic(todos, (s, t) => [...s, t]);
async function save(formData: FormData) {
addOptimistic({ title: formData.get("title"), pending: true });
await createTodo(formData); // server state replaces the optimistic one
}
return <form action={save}>…</form>;
In short
- You can often drop
useMemo/useCallbackbecause the compiler auto-memoises at build time. Profile before adding them back (Front-end Performance Checklist). - The transition wraps the update; the deferred value wraps the value.
- A rejected
use(promise)is caught by the nearest error boundary.
- #react
- #react-19
- #hooks
- #performance
↩ Linked from (2)
…sort, paginate) and for stable callbacks into memoised children. React 19's compiler automates most of this (React 19 Hooks Cheat Sheet). Avoid parent-driven re-renders. Keep state low and use selector stores (Zustand T…
…t the root as a last resort. use(promise) and Suspense data fetching send rejections to the nearest boundary (React 19 Hooks Cheat Sheet); TanStack Query's throwOnError does the same.
↪ Links to (3)
Related by topic
- Seed
Browser Fundamentals for Front-end Engineers
Frontend craft - Seedcase study
Building and Levelling Up a UI Team
Career - Seed
Contract-Driven Development
Platform engineering - Seed
React Data Fetching Patterns
Frontend craft