← Back to BlogArticle

React 19 Server Actions: Best Practices for 2026

React 19 brings Server Actions to stability with major improvements. Combined with Next.js 16, they provide a powerful pattern for handling form submissions and data mutations without API routes.

Basic Server Action

Define a server action in your component or separate file:

'use server'
import { revalidatePath } from 'next/cache'

export async function createPost(formData: FormData) {
  const title = formData.get('title') as string
  
  await db.posts.create({ title })
  revalidatePath('/blog')
  
  return { success: true }
}

Using useActionState

React 19's useActionState provides built-in state management for forms:

'use client'
import { useActionState } from 'react'
import { createPost } from './actions'

export function CreatePostForm() {
  const [state, action, isPending] = useActionState(createPost, null)
  
  return (
    <form action={action}>
      <input name="title" />
      <button disabled={isPending}>
        {isPending ? 'Creating...' : 'Create'}
      </button>
      {state?.success && <p>Created!</p>}
    </form>
  )
}

Error Handling

Return errors from your server action:

'use server'
export async function createPost(prevState, formData) {
  const title = formData.get('title')
  
  if (!title || title.length < 3) {
    return { error: 'Title must be at least 3 characters' }
  }
  
  // ... mutation logic
  return { success: true }
}

Best Practices

  • Use 'use server' at the top of files for clean organization
  • Always revalidatePath() after mutations
  • Validate input on the server, even with client validation
  • Use useActionState for pending states and error handling
  • Keep actions in separate files for large applications

When to Use Server Actions

  • Form submissions
  • Data mutations (create, update, delete)
  • Anything that doesn't need a public API

When NOT to Use Server Actions

  • Public API endpoints (use Route Handlers)
  • Third-party integrations
  • Streaming data (use Server Components)