前端框架

-

React Server Action 的全面講解

this.web

React Server Action 封面

React 和 Next.js 這幾年更新得非常快,特別是 Next.js 13/14 推出的 App Router,帶來了許多全新的觀念。

其中一個讓我剛開始完全搞不懂的功能,就是 Server Action

如果你有在使用 React 或 Next.js,但還不清楚 Server Action,這篇文章會用淺顯易懂的方式,帶你快速理解 Server Action 是什麼、能做什麼,以及它的優缺點。

Server Action 的介紹

Server Action = 能在伺服器執行的函數。

你可以在直接 Server Component 去使用它,或在 Client Component 搭配 useEffect、事件、form 表單做使用。

有了 Server Action,我們就能直接對資料庫進行增刪改查,或執行任何必須在伺服器端完成的操作。

由於 Server Action 不只可以修改資料,也能單純用來讀取資料,React 團隊後來將它改名為 Server Function。不過在 Next.js 官方文件中,仍以 Server Action 稱呼。

為什麼前端工程師要學 Server Action?

對大部分的前端來說,傳統的前後端互動流程通常是::

前端負責 UI → 發送 API 請求 → 後端處理邏輯 → 回傳結果給前端

API 流程示意圖

這個流程在大多數情況下沒有問題,但在以下兩種情境裡,如果僅用傳統的 API 呼叫方式,就會有點麻煩:

一、使用類似 Supabase 的資料庫服務

現在的 BaaS(Backend as a Service)服務越來越強大,前端開發者不需要後端團隊,也能用像 Supabase 這樣的服務快速完成專案。

雖然我們可以直接用 Supabase Key 在並搭配 RLS 在前端呼叫資料庫,但在實務上,透過伺服器端存取資料還是會更安全

Server Action 提供了這個管道,讓我們不用再額外寫 API,就能在伺服器上直接進行資料庫操作。

二、更新 Next 的快取機制

Next.js 有很強大的快取機制(可以參考這篇貼文

通常在後端資更新時,我們會用 revalidateTag 或 revalidatePath 告訴 Next 說取消快取,有新資料了。

但由於 Next.js 快取是在伺服器端做的,如果是傳統在 Client Component Call API 的方式就沒辦法 revalidate,Server Action 則完美解決了這個問題。我們能直接在 Server Action 去 revalidate

所以如果你未來要在 Next.js App Router 上做專案,了解 Server Action 幾乎是一個基本功。

Server Action 的基本應用

基本了解 Server Action 後,我們來用一個簡單範例展示 Server Action 的用法,假設我們用 Supabase 做資料庫,並想要新增留言功能::

export default async function Page() {
  // 定義 Server Action
  async function addMessage(formData: FormData) {
    "use server"

    // 這邊簡單示意,使用時還是要考慮驗證和安全性!
    const content = formData.get("content") as string
    await supabase.from('messages').insert({ content })

    revalidatePath('/') // 告訴 Next.js 忘記快取,抓新資料
  }

  return (
    <form action={addMessage}>
      <input name="content" placeholder="輸入留言..." required />
      <button type="submit">送出</button>
    </form>
  )
}

整個流程大致如下:

  1. addMessage 加了 "use server",就是一個 Server Action。
  2. 表單 <form action={addMessage}> 會自動把輸入送到伺服器執行。
  3. 插入資料後,用 revalidatePath('/') 清掉首頁快取,Next.js 會重新抓資料並更新 UI。

如果沒有 Server Action,我們就需要自己寫 API Router,並用 fetch 的方式呼叫,非常麻煩

const res = await fetch('/api/messages', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ content }),
})

Server Action 的原理

在我一開始接觸到 Server Action 時,覺得很神奇,為什麼不用寫 API 卻能再前端執行 Server Side 的函數?

事實上,Server Action 底層仍然是透過 API 呼叫伺服器,只是 Next.js 自動幫你生成並管理這個 API,讓開發者不需要手動維護。

例如在下方的帳號管理功能中,updateUserProfile 是一個 Server Action:

const onSubmit = async (data: ProfileFormData) => {
    try {
        // updateUserProfile 是一個 Server Action
        const result = await updateUserProfile(data);

        if (result.success) {
            toast.success('更新成功');
        }
    } catch {
        toast.error('更新失敗,請稍後再試');
    }
};

當我們更新資料並送出後,瀏覽器實際上仍會向伺服器發送一個 POST 請求,只是這個 API 是由 Next.js 自動生成的。

Server Action 的優缺點

最後我們來看一下 Server Action 的優缺點:

優點

  • 減少樣板程式碼:不用再手動寫 /api 路由與 fetch 請求。
  • 更直覺:可以像呼叫函數一樣處理資料。
  • 和 Next.js、React 深度整合:能直接搭配 revalidatePath 重新驗證快取,或用 useActionState 管理 loading 狀態。

缺點

  • 只在 Next.js App Router 用得到:如果團隊沒用 Next.js 13/14,基本上沒機會用。
  • 只適合單一 Web 前端:如果還有手機 App、第三方需要共用 API,那就還是得寫傳統後端。
  • 安全與治理有限:金流、稽核、法遵,還是要正式後端來控,不能全丟給 Server Action。
  • 有「隱藏 API」的風險:雖然開發方便,但底層還是 POST 請求,要注意權限檢查、安全性,如果在 Server Action 去 Call 後端會多一次的 request。

結語

Server Action 不會取代後端,而是讓前端在某些情況下可以更直接的操作資料庫,開發更快速,如果你是 React 或 Next.js 開發者,還是蠻推薦了解一下 Server Action 的~

參考資料:

你可能會感興趣的文章 👇