Skip to content

Module 4: Server Actions & Mutations

⚡ Module 4: Server Actions & Mutations

In this module, we move from manual fetch('POST') calls and API route boilerplate to Server Actions.

🏗️ 1. The Mechanic: Manual Mutations

In a traditional React/API setup, updating data requires creating an endpoint and a complex client-side handler.

🧩 The Problem: Mutation Toil

  1. Create an API route (/api/update-user).
  2. Write a client function with fetch('POST', { ... }).
  3. Manually handle isLoading, isError.
  4. Manually re-fetch the data to see the update.

The Manual Pattern:

function UpdateProfile() {
  async function onSubmit(e) {
    e.preventDefault();
    await fetch('/api/update-user', { method: 'POST', body: JSON.stringify(...) });
    // Now I have to manually update the UI state!
  }
  return <form onSubmit={onSubmit}>...</form>;
}

🏗️ 2. The Abstraction: Server Actions

Server Actions are functions that run on the server but can be called directly from your client components (via forms or events).

The Next.js Way:

// app/profile/page.tsx
export default function Page() {
  async function updateName(formData: FormData) {
    'use server';
    const name = formData.get('name');
    await db.user.update({ data: { name } });
    revalidatePath('/profile'); // Automatically updates the UI!
  }

  return (
    <form action={updateName}>
      <input name="name" type="text" />
      <button type="submit">Save</button>
    </form>
  );
}

🧩 The Benefit: Progressively Enhanced Forms

Server Actions work even if the user’s browser has JavaScript disabled (using standard HTML Form behavior), while also providing a fast, seamless experience when JS is enabled.


🧪 Professor’s Challenge: Optimistic UI

Task: Research useOptimistic.

  1. Try to build a Todo list where the item is added to the screen immediately before the server finishes saving it.
  2. Note how this improves perceived performance for the end user.