Full Stack 24:152025-05-22

React Server Actions: Forms Without the Boilerplate

Server Actions changed how we build forms in Next.js. No more API routes for simple mutations — just a function, a form, and a pending state. Here's how to use them properly.

Watch on YouTube

Click to open in YouTube

Video Notes & Code

Key takeaways, code snippets, and resources from this video.

Basic Server Action

tsx
// app/contact/actions.ts
'use server'

import { z } from 'zod'
import { revalidatePath } from 'next/cache'

const schema = z.object({
  name: z.string().min(2),
  email: z.string().email(),
  message: z.string().min(10),
})

export async function submitContact(formData: FormData) {
  const parsed = schema.safeParse(Object.fromEntries(formData))
  if (!parsed.success) {
    return { error: parsed.error.flatten().fieldErrors }
  }
  await db.insert(contacts).values(parsed.data)
  revalidatePath('/contact')
  return { success: true }
}

// Form component
export default function ContactForm() {
  return (
    <form action={submitContact}>
      <input name="name" required />
      <input name="email" type="email" required />
      <textarea name="message" required />
      <button type="submit">Send</button>
    </form>
  )
}

Found this useful?

Subscribe for weekly content on AI engineering, SaaS building, and full stack development.

Book a Call