C.W.K.
Lesson 06 of 06 · published

React 19 Modern — use(), Actions, Concurrent

~13 min · react19, use, actions

Level 0Curious
0 XP0/52 lessons0/16 achievements
0/100 XP to next level100 XP to go0% complete

use() — read promises and contexts inline

React 19 introduced use(): a hook that reads a promise (suspending if it's pending) or a context (just like useContext). Unlike useContext, you can call use() conditionally and inside loops. That's the breakthrough — it stops being a special-case 'rules of hooks' violation.

Actions — form submissions that just work

Actions are async functions you bind to forms. React handles the pending state, errors, and optimistic updates for you. useActionState gives you the latest result + a pending flag without any of the setLoading(true); try { ... } finally { setLoading(false); } ritual.

The compiler — automatic memoization

The React Compiler (still in beta during cwkPippa's build, but landing soon) auto-memoizes components and hooks at compile time. The era of manually wrapping everything in useMemo and useCallback is ending. Your code stays clean, performance stays good.

Don't over-optimize manually: If you're reaching for useMemo on something the compiler will memoize for free, you're adding noise. Profile first. Optimize only the things that show up hot.

Code

use() with a promise — inline async data·tsx
function ConversationDetail({ conversationPromise }: { conversationPromise: Promise<Conversation> }) {
  // Suspends until the promise resolves; <Suspense> above renders fallback.
  const conversation = use(conversationPromise);
  return <ChatView conversation={conversation} />;
}
Actions — useActionState for a save form·tsx
async function saveTitle(prevState: State, formData: FormData) {
  const title = formData.get('title') as string;
  await fetch('/api/conversation/title', { method: 'PATCH', body: JSON.stringify({ title }) });
  return { title, error: null };
}

function TitleEditor() {
  const [state, formAction, isPending] = useActionState(saveTitle, { title: '', error: null });
  return (
    <form action={formAction}>
      <input name="title" defaultValue={state.title} disabled={isPending} />
      <button type="submit" disabled={isPending}>{isPending ? 'Saving…' : 'Save'}</button>
    </form>
  );
}

Progress

Progress is local-only — sign in to sync across devices.