CodePark/ questions / Server Actions
START PRACTICINGPRACTICE
Frontend question · Next.js › Server Actions

How do Server Actions work with forms, and what is progressive enhancement here?

// app/actions.ts
"use server";
export async function createPost(prevState: { error?: string }, formData: FormData) {
  const title = formData.get("title");
  if (typeof title !== "string" || !title) return { error: "Title is required" };
  await db.post.create({ data: { title } });
  return {};
}

// NewPost.tsx
"use client";
const [state, formAction, pending] = useActionState(createPost, {});
// <form action={formAction}> ... {state.error} ...</form>

You pass a Server Action to a form's action prop. Progressive enhancement means the form works even before JavaScript loads.

How it works. On submit, React sends the FormData to the action. The action reads fields with formData.get("title"), validates them and saves.

Progressive enhancement. If a Server Component renders the form, it works before JavaScript loads, or with JavaScript turned off. The browser submits it as a normal POST. Once the page is hydrated (React has attached its event handlers), React submits it without a full page reload.

Feedback in Client Components:

  • useActionState wraps the action. It gives you the last state the action returned, such as validation errors, and a pending flag.
  • useFormStatus lets a child of the form, like a submit button, read whether the form is submitting.
  • Pass the Server Action to <form action>.
  • The action receives the form's FormData.
  • Server-rendered forms can submit without JavaScript.
  • useActionState gives the returned state and a pending flag.
  • useFormStatus reads the pending state from inside the form.