Next.js Server Actions
Run server-side mutations directly from components without building API endpoints
Overview
Server Actions are async functions that run on the server and can be invoked from forms or event handlers. Marked with the 'use server' directive, they let you handle mutations without manually creating API routes. They integrate with progressive enhancement, work without JavaScript, and can revalidate cached data after writing.
Syntax / Usage
Define an action with 'use server' at the top of the function or file, then pass it to a form's action prop.
// app/actions.ts
'use server'
import { revalidatePath } from 'next/cache'
import { redirect } from 'next/navigation'
export async function createPost(formData: FormData) {
const title = formData.get('title') as string
await db.post.create({ data: { title } })
revalidatePath('/posts')
redirect('/posts')
}
// app/posts/new/page.tsx (Server Component)
import { createPost } from '@/app/actions'
export default function NewPostPage() {
return (
<form action={createPost}>
<input name="title" required />
<button type="submit">Create</button>
</form>
)
}
Examples
Handle pending UI state from a Client Component with useFormStatus:
'use client'
import { useFormStatus } from 'react-dom'
export function SubmitButton() {
const { pending } = useFormStatus()
return <button disabled={pending}>{pending ? 'Saving…' : 'Save'}</button>
}
Return validation errors with useActionState:
'use client'
import { useActionState } from 'react'
import { subscribe } from '@/app/actions'
export function Newsletter() {
const [state, action] = useActionState(subscribe, { error: null })
return (
<form action={action}>
<input name="email" type="email" />
{state.error && <p>{state.error}</p>}
<button>Subscribe</button>
</form>
)
}
Common Mistakes
- Forgetting the
'use server'directive, so the function runs on the client - Trusting
formDatainput without server-side validation - Not calling
revalidatePathorrevalidateTagafter a mutation, leaving stale UI - Importing a Server Action into a Client Component file that lacks
'use server'in the action module - Returning non-serializable values from an action
See Also
nextjs-route-handlers nextjs-data-fetching server-components