Module P-3·18 min read

How to make Server Actions feel instant — useOptimistic for immediate UI updates, useActionState for form state management, pending state patterns, and rolling back on error. The bridge between server-actions-mutations and at-scale.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

Optimistic UI: useOptimistic, useActionState, and the Pending State Pattern

Who this module is for: You have Server Actions working — the form submits, the data saves, the page updates. But the UI feels sluggish: users click a button and stare at a spinner while the server round-trip completes. This module covers the three React 19 hooks that make Server Actions feel instant — useOptimistic for immediate UI updates, useActionState for form state management, and the pending state pattern for visual feedback.


Why Optimistic UI Matters

A Server Action invokes a round-trip to your server: the browser sends a request, Next.js executes the action, revalidates the cache, and the updated UI flows back down. Even on a fast connection, this takes 200–800ms. On a mobile network, 1–3 seconds.

Users have been conditioned by native apps and real-time UIs to expect instant feedback. A button that does nothing for 500ms feels broken. Optimistic UI solves this by updating the UI immediately — before the server confirms — and rolling back if the server reports an error.

The pattern has three layers:

  1. Pending state — show that something is happening (spinner, disabled state)
  2. Optimistic update — show the expected result immediately
  3. Rollback — revert if the server returns an error

React 19 provides a hook for each layer.


useActionState: Form State Management

useActionState (formerly useFormState in React 18) connects a Server Action to a component's state. It gives you the action's return value and a wrapped action function that you pass to a form.

tsx
typescript

What useActionState gives you:

  • state — the most recent return value from the Server Action (or initial state on first render)
  • action — a wrapped version of your Server Action to pass to <form action={action}>
  • isPendingtrue while the action is in flight

The signature change: your Server Action must accept prevState as the first argument before formData. The prevState is the previous return value — useful for accumulating state across multiple submissions.


useOptimistic: Instant UI Updates

useOptimistic lets you show a temporary "optimistic" value while an async operation is pending, then automatically revert to the actual value when the operation completes.

tsx

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.