React SME Cookbook
All FAQs

Search Documentation

Search across all documentation pages

react-19overviewmigrationnew-features

What's New in React 19 - A complete summary of every major feature and breaking change

Recipe

React 19 is a major release that introduces server-first architecture, new hooks, and automatic optimizations. Here is the quick-reference checklist of what shipped:

Feature                         Category
-------                         --------
Server Components (RSC)         Architecture
Server Actions                  Data mutations
Form Actions                    DOM integration
use() hook                      Data fetching / context
useActionState                  Form state management
useFormStatus                   Pending UI
useOptimistic                   Optimistic updates
ref as prop                     API simplification
Document Metadata               SEO / head management
Asset Loading APIs              Performance
React Compiler                  Auto-memoization

When to reach for this: Read this page first when starting a new React 19 project or planning a migration from React 18.

Working Example

// A single component that touches many React 19 features at once
import { use, useOptimistic, useActionState } from "react";
import { saveComment } from "./actions"; // server action
 
type Comment = { id: string; text: string };
 
function CommentThread({ commentsPromise }: { commentsPromise: Promise<Comment[]> }) {
  // use() unwraps the promise (Suspense-aware)
  const comments = use(commentsPromise);
 
  // useOptimistic for instant feedback
  const [optimistic, addOptimistic] = useOptimistic(
    comments,
    (state, newText: string) => [...state, { id: "temp", text: newText }]
  );
 
  // useActionState to wire up a server action
  const [_state, formAction, isPending] = useActionState(
    async (_prev: Comment[], formData: FormData) => {
      const text = formData.get("text") as string;
      addOptimistic(text);
      await saveComment(text);
      return [...comments, { id: crypto.randomUUID(), text }];
    },
    comments
  );
 
  return (
    <section>
      {/* Document metadata hoisted to <head> automatically */}
      <title>Comments ({optimistic.length})</title>
      <meta name="description" content="Live comment thread" />
 
      <ul>
        {optimistic.map((c) => (
          <li key={c.id}>{c.text}</li>
        ))}
      </ul>
 
      <form action={formAction}>
        <input name="text" required />
        <button disabled={isPending}>Post</button>
      </form>
    </section>
  );
}
 
// ref as prop - no forwardRef needed
function FancyInput({ placeholder, ref }: { placeholder: string; ref?: React.Ref<HTMLInputElement> }) {
  return <input placeholder={placeholder} ref={ref} />;
}
 
export { CommentThread, FancyInput };

What this demonstrates:

  • use() unwrapping a promise inside a component
  • useOptimistic for instant UI feedback
  • useActionState binding a server action to a form
  • Document metadata (<title>, <meta>) rendered inline
  • ref received as a regular prop without forwardRef

Deep Dive

How It Works

  • Server Components run exclusively on the server and send serialized UI to the client. They can access databases, file systems, and secrets directly without exposing them to the browser.
  • Server Actions are async functions marked with "use server" that the framework turns into RPC endpoints. They can be passed to forms, called from event handlers, or invoked from transitions.
  • Form Actions let you pass an async function to <form action={fn}>. React manages the pending state, error handling, and optimistic updates automatically.
  • use() is a new API (not technically a hook -- it can be called conditionally) that reads promises and context values. When reading a promise, it integrates with Suspense boundaries.
  • useActionState replaces the experimental useFormState. It returns [state, action, isPending] and works both on the client and with progressive enhancement on the server.
  • useFormStatus exposes the pending status of the nearest parent <form> to any descendant component.
  • useOptimistic provides a pattern for showing an optimistic value while an async action is in flight, reverting automatically if the action fails.
  • ref as prop means forwardRef is no longer required. Function components receive ref as a regular prop. forwardRef still works but is deprecated and will be removed in a future version.
  • Document Metadata tags (<title>, <meta>, <link>) rendered anywhere in the component tree are automatically hoisted to <head>.
  • Asset Loading APIs (preload, preinit, prefetchDNS, preconnect) from react-dom let you eagerly load fonts, scripts, and stylesheets.
  • React Compiler (formerly React Forget) automatically memoizes components and hooks, eliminating the need for manual useMemo, useCallback, and React.memo in most cases.

Variations

React 19 works in two main modes:

  • Client-only SPA -- You get form actions, use(), optimistic updates, metadata hoisting, and the compiler. No server components or server actions.
  • Full-stack framework (Next.js, Remix, etc.) -- You additionally get server components and server actions with streaming SSR.

TypeScript Notes

  • React 19 ships updated @types/react and @types/react-dom (version 19+). Install them together.
  • ref is now part of the props type. If you use React.ComponentProps<typeof MyComponent>, it will include ref automatically.
  • useActionState is generic: useActionState<State>(action, initialState).
  • The use() function is generic: use<T>(resource: Promise<T> | React.Context<T>): T.

Gotchas

  • Hydration error improvements -- React 19 logs a single diff-style error instead of multiple cryptic messages. Fix: Upgrade to see cleaner errors, but you still must fix mismatches.
  • Strict Mode double-firing -- Still present in development. Fix: Ensure effects are idempotent; this is unchanged from React 18.
  • useActionState vs useFormState -- useFormState was renamed. Fix: Replace all useFormState imports with useActionState from "react" (not "react-dom").
  • forwardRef deprecation -- forwardRef still works but triggers a deprecation warning in development. Fix: Refactor to accept ref as a regular prop.
  • Context as a provider -- <Context> can now be rendered directly instead of <Context.Provider>. The .Provider syntax still works but is deprecated. Fix: Replace <MyContext.Provider value={v}> with <MyContext value={v}>.
  • ref cleanup functions -- Ref callbacks can now return a cleanup function (like effects). Returning anything else (including undefined implicitly) will be flagged. Fix: If your ref callback returns nothing, ensure it explicitly returns undefined or returns a cleanup.

Alternatives

ApproachWhen to choose
Stay on React 18Large app with no immediate need for server components or new hooks
Incremental adoptionAdd "use client" to existing components and adopt React 19 features file-by-file
Full rewrite with RSCGreenfield project using Next.js 15+ or a framework with RSC support
React 19 client-onlySPA that benefits from use(), optimistic updates, and the compiler without server infra

FAQs

What is the main architectural shift in React 19 compared to React 18?
  • React 19 introduces a server-first architecture with Server Components (RSC) as the default rendering model
  • Components run on the server by default and ship zero JavaScript to the browser unless marked with "use client"
  • This is complemented by Server Actions for data mutations, eliminating the need for separate API routes in many cases
Which new hooks and APIs shipped in React 19?
  • use() for reading promises and context (can be called conditionally)
  • useActionState for form state management (replaces useFormState)
  • useFormStatus for pending UI in form descendants
  • useOptimistic for instant optimistic updates
  • Asset loading APIs: preload, preinit, prefetchDNS, preconnect
Can I use React 19 features without a server framework like Next.js?
  • Yes. In a client-only SPA you get form actions, use(), optimistic updates, metadata hoisting, and the React Compiler
  • Server Components and Server Actions require a framework with RSC support (e.g., Next.js 15+, Remix)
What happened to useFormState? I see references to useActionState instead.
  • useFormState was renamed to useActionState before the stable release
  • Import it from "react", not "react-dom"
  • The signature is useActionState(action, initialState) returning [state, action, isPending]
How does document metadata work inline in React 19?

Tags like <title>, <meta>, and <link> rendered anywhere in the component tree are automatically hoisted to <head>:

function Page() {
  return (
    <div>
      <title>My Page</title>
      <meta name="description" content="Hello" />
      <h1>Content</h1>
    </div>
  );
}
Do I still need forwardRef in React 19?
  • No. Function components now receive ref as a regular prop
  • forwardRef still works but is deprecated and will be removed in a future version
  • Migrate by moving ref from the forwardRef second argument into the props object
Gotcha: What happens if I return something from a ref callback that is not a cleanup function?
  • React 19 allows ref callbacks to return a cleanup function (like effects)
  • Returning anything else (including implicitly returning undefined from an arrow function expression) will be flagged as a warning
  • Ensure your ref callback either returns nothing explicitly or returns a cleanup function
Gotcha: Does Strict Mode still double-fire effects in React 19?
  • Yes. Strict Mode double-firing in development is unchanged from React 18
  • Effects must be idempotent -- running them twice should not cause different behavior
  • This is a development-only behavior and does not affect production builds
How do I type useActionState generically in TypeScript?
const [state, action, isPending] = useActionState<MyState>(
  async (prev: MyState, formData: FormData) => {
    // return new state
    return { ...prev, updated: true };
  },
  { updated: false }
);
  • useActionState is generic: useActionState<State>(action, initialState)
  • The action signature is (prevState: State, formData: FormData) => Promise<State>
How is the use() function typed in TypeScript?
  • use<T>(resource: Promise<T> | React.Context<T>): T
  • The resolved type is inferred from the promise or context type
  • It is imported from "react": import { use } from "react"
What does the React Compiler do and do I need to change my code?
  • The compiler (formerly React Forget) automatically memoizes components and hooks at build time
  • It eliminates the need for manual useMemo, useCallback, and React.memo in most cases
  • No code changes are required -- existing manual memoization is compatible
What is the difference between use() and useContext()?
  • use() can be called conditionally (inside if blocks, loops, early returns) while useContext cannot
  • use() also accepts promises, not just context objects
  • use(context) is the preferred replacement for useContext(context) going forward
How should I approach migrating a large React 18 app to React 19?
  • Incremental adoption is recommended: add "use client" to existing components and adopt features file-by-file
  • Install React 19 types (@types/react and @types/react-dom version 19+) together
  • Replace useFormState imports with useActionState from "react"
  • Replace <Context.Provider> with <Context value={v}> (optional, old syntax still works)