Next.js Server Actions 伺服器動作與資料變更

在傳統的 Web 開發中,如果你想讓使用者提交表單,你需要先寫一個 API 端點,然後在前端使用 fetch 並處理 JSON。

Server Actions 徹底簡化了這個過程。它允許你定義一個非同步函式,並直接從前端組件中呼叫,Next.js 會在背後自動幫你建立 API 連結並確保通訊安全。

什麼是 Server Actions?

Server Actions 是建立在 React Actions 基礎上的功能。它們是宣告為 'use server' 的函式,可以直接作為 <form>action 屬性,或者在點擊事件、useEffect 中觸發。

優點:

  • 減少樣板程式碼:不用再寫 API Route。
  • 類型安全:如果你使用 TypeScript,參數類型會自動保持一致。
  • 漸進式增強:即使 JavaScript 還沒載入(或是停用檔案),表單提交依然有效。

基本用法

你可以直接在 Server Component 中定義 Action,或者將它們放在獨立的檔案中。

範例:新增留言

// app/blog/actions.ts
'use server'; // 必須標榜為伺服器動作

import { revalidatePath } from 'next/cache';

export async function createComment(formData: FormData) {
  const content = formData.get('content');

  // 1. 執行伺服器邏輯,例如寫入資料庫
  // await db.comment.create({ data: { content } });

  console.log('收到的留言內容:', content);

  // 2. 告訴 Next.js 重新擷取該路徑的資料,以更新 UI
  revalidatePath('/blog');
}

在頁面中使用:

// app/blog/page.tsx
import { createComment } from './actions';

export default function CommentForm() {
  return (
    <form action={createComment}>
      <textarea name="content" className="border p-2 w-full" />
      <button type="submit" className="bg-black text-white px-4 py-2 mt-2">
        提交留言
      </button>
    </form>
  );
}

在 Client Components 中呼叫

雖然 Actions 運行在伺服器,但你也可以在標註為 'use client' 的組件中使用它們(例如為了處理 Loading 狀態)。

使用 useActionState (React 19+)

這是 React 19 與 Next.js 16 推薦的進階用法,用於處理表單狀態(如錯誤訊息、Loading):

'use client';

import { useActionState } from 'react';
import { createComment } from './actions';

export default function ClientForm() {
  // state 為 Action 回傳的值,formAction 為包裝後的 Action
  const [state, formAction, isPending] = useActionState(createComment, null);

  return (
    <form action={formAction}>
      <input name="content" />
      <button disabled={isPending}>{isPending ? '傳送中...' : '提交'}</button>
      {state?.error && <p className="text-red-500">{state.error}</p>}
    </form>
  );
}

安全性考量

Next.js 為 Server Actions 內建了以下安全防護:

  • 路徑驗證:確保 Action 只在合法的路徑發起。
  • CSRF 防護:自動抵禦跨站請求偽造。
  • Dead Code Elimination:不在瀏覽器中洩漏 Action 的伺服器端邏輯。
雖然 Server Actions 很方便,但請記住這依然是「存取後端」的函式。你必須在 Action 內部執行身份驗證與權限檢查,確保使用者有權執行該動作。