伺服器動作 (Server Actions)

Next.js 與 React Actions 整合,提供了內建的伺服器變更 (server mutations)解決方案。

慣例

您可以在 Next.js 專案中啟用實驗性serverActions 標記來使用伺服器動作 (Server Actions)。

next.config.js
module.exports = {
  experimental: {
    serverActions: true,
  },
}

伺服器動作 (Server Actions) 可以在以下兩個地方定義:

  • 在使用它的元件內部(僅限伺服器元件 (Server Components))。
  • 在單獨的檔案中(客戶端與伺服器元件 (Client and Server Components)),以便重複使用。您可以在單一檔案中定義多個伺服器動作。

使用伺服器元件 (Server Components)

透過在函式主體頂部加上 "use server" 指令來建立非同步函式,即可建立伺服器動作 (Server Action)。"use server" 確保此函式僅在伺服器上執行。

此函式應具有可序列化的參數可序列化的回傳值

app/page.js
export default function ServerComponent() {
  async function myAction() {
    'use server'
    // ...
  }
}

使用客戶端元件 (Client Components)

匯入

在單獨的檔案中建立伺服器動作 (Server Action),並在檔案頂部加上 "use server" 指令。然後,將伺服器動作匯入到您的客戶端元件 (Client Component):

app/actions.js
'use server'

export async function myAction() {
  // ...
}
app/client-component.jsx
'use client'

import { myAction } from './actions'

export default function ClientComponent() {
  return (
    <form action={myAction}>
      <button type="submit">加入購物車</button>
    </form>
  )
}

須知:當使用頂層 "use server" 指令時,下方的所有匯出都會被視為伺服器動作 (Server Actions)。您可以在單一檔案中包含多個伺服器動作。

屬性 (Props)

在某些情況下,您可能希望將伺服器動作 (Server Action) 作為屬性 (prop) 傳遞給客戶端元件 (Client Component)。

<ClientComponent updateItem={updateItem} />
app/client-component.jsx
'use client'

export default function ClientComponent({ myAction }) {
  return (
    <form action={myAction}>
      <input type="text" name="name" />
      <button type="submit">更新項目</button>
    </form>
  )
}

綁定參數

您可以使用 bind 方法將參數綁定到伺服器動作 (Server Action)。這允許您建立一個已綁定部分參數的新伺服器動作。當您想傳遞額外參數給伺服器動作時,這非常有用。

app/client-component.jsx
'use client'

import { updateUser } from './actions'

export function UserProfile({ userId }) {
  const updateUserWithId = updateUser.bind(null, userId)

  return (
    <form action={updateUserWithId}>
      <input type="text" name="name" />
      <button type="submit">更新使用者名稱</button>
    </form>
  )
}

然後,updateUser 伺服器動作 (Server Action) 將始終接收 userId 參數,以及表單資料:

app/actions.js
'use server'

export async function updateUser(userId, formData) {
  // ...
}

須知:伺服器動作 (Server Action) 的 .bind 方法在伺服器和客戶端元件 (Server and Client Components) 中均可使用。它也支援漸進增強 (Progressive Enhancement)

呼叫方式

您可以透過以下方法呼叫伺服器動作 (Server Actions):

  • 使用 action:React 的 action 屬性允許在 <form> 元素上呼叫伺服器動作。
  • 使用 formAction:React 的 formAction 屬性允許處理 <form> 中的 <button><input type="submit"><input type="image"> 元素。
  • 使用 startTransition 自訂呼叫:不使用 actionformAction,而是使用 startTransition 來呼叫伺服器動作。此方法會停用漸進增強 (Progressive Enhancement)

漸進增強 (Progressive Enhancement)

漸進增強允許 <form> 在沒有 JavaScript 或 JavaScript 被停用的情況下正常運作。這使得使用者即使在表單的 JavaScript 尚未載入或載入失敗時,仍能與表單互動並提交資料。

React Actions(伺服器和客戶端)支援漸進增強,使用以下兩種策略之一:

  • 如果直接將**伺服器動作 (Server Action)**傳遞給 <form>,即使 JavaScript 被停用,表單仍可互動。
  • 如果將**客戶端動作 (Client Action)**傳遞給 <form>,表單仍可互動,但動作會被放入佇列,直到表單完成水合 (hydrated)。React 會優先處理該動作,因此它仍會快速執行。

在這兩種情況下,表單在水合 (hydration) 發生前即可互動。儘管伺服器動作 (Server Actions) 具有不依賴客戶端 JavaScript 的額外優勢,您仍然可以在需要時與客戶端動作 (Client Actions) 組合其他行為,而不犧牲互動性。

大小限制

預設情況下,傳送給伺服器動作 (Server Action) 的請求主體 (request body) 最大大小為 1MB,以防止解析大量資料時消耗過多的伺服器資源。

然而,您可以使用 serverActionsBodySizeLimit 選項來配置此限制。它可以接受位元組數或任何 bytes 支援的字串格式,例如 1000'500kb''3mb'

next.config.js
module.exports = {
  experimental: {
    serverActions: true,
    serverActionsBodySizeLimit: '2mb',
  },
}

其他資源

以下 React API 頁面目前正在撰寫文件中:

  • "use server"
  • action (🚧)
  • formAction (🚧)
  • useFormStatus (🚧)
  • useFormState (🚧)
  • useOptimistic (🚧)

On this page