伺服器函式

React 伺服器元件

伺服器函式用於 React 伺服器元件 中。

注意:在 2024 年 9 月之前,我們將所有伺服器函式稱為「伺服器動作」。如果伺服器函式被傳遞給動作屬性或從動作內部呼叫,則它是一個伺服器動作,但並非所有伺服器函式都是伺服器動作。此文件中已更新命名以反映伺服器函式可用於多種用途。

伺服器函式允許客戶端元件呼叫在伺服器上執行的非同步函式。

注意

如何建置對伺服器函式的支援?

雖然 React 19 中的伺服器函式很穩定,並且在主要版本之間不會中斷,但在 React 伺服器元件組合器或框架中用於實作伺服器函式的底層 API 不遵循語義化版本控制,並且可能在 React 19.x 的次要版本之間中斷。

為了支援伺服器函式作為組合器或框架,我們建議固定到特定 React 版本,或使用 Canary 版本。我們將繼續與組合器和框架合作,在未來穩定用於實作伺服器函式的 API。

當使用 "use server" 指令定義伺服器函式時,您的框架會自動建立對伺服器函式的參考,並將該參考傳遞給客戶端元件。當在客戶端上呼叫該函式時,React 會將請求發送到伺服器以執行該函式,並傳回結果。

可以在伺服器元件中建立伺服器函式並將其作為屬性傳遞給客戶端元件,或者可以將其導入並在客戶端元件中使用。

用法

從伺服器元件建立伺服器函式

伺服器元件可以使用 "use server" 指令定義伺服器函式

// Server Component
import Button from './Button';

function EmptyNote () {
async function createNoteAction() {
// Server Function
'use server';

await db.notes.create();
}

return <Button onClick={createNoteAction}/>;
}

當 React 渲染 EmptyNote 伺服器函式時,它會建立對 createNoteAction 函式的參考,並將該參考傳遞給 Button 客戶端元件。當按下按鈕時,React 會將請求發送到伺服器,以使用提供的參考執行 createNoteAction 函式

"use client";

export default function Button({onClick}) {
console.log(onClick);
// {$$typeof: Symbol.for("react.server.reference"), $$id: 'createNoteAction'}
return <button onClick={() => onClick()}>Create Empty Note</button>
}

更多資訊,請參閱 "use server" 的文件。

從客戶端元件導入伺服器函式

客戶端元件可以從使用 "use server" 指令的檔案導入伺服器函式

"use server";

export async function createNote() {
await db.notes.create();
}

當組合器建置 EmptyNote 客戶端元件時,它會在組合中建立對 createNoteAction 函式的參考。當按下 button 時,React 會將請求發送到伺服器,以使用提供的參考執行 createNoteAction 函式

"use client";
import {createNote} from './actions';

function EmptyNote() {
console.log(createNote);
// {$$typeof: Symbol.for("react.server.reference"), $$id: 'createNoteAction'}
<button onClick={() => createNote()} />
}

更多資訊,請參閱 "use server" 的文件。

具有動作的伺服器函式

可以從客戶端上的動作呼叫伺服器函式

"use server";

export async function updateName(name) {
if (!name) {
return {error: 'Name is required'};
}
await db.users.updateName(name);
}
"use client";

import {updateName} from './actions';

function UpdateName() {
const [name, setName] = useState('');
const [error, setError] = useState(null);

const [isPending, startTransition] = useTransition();

const submitAction = async () => {
startTransition(async () => {
const {error} = await updateName(name);
if (!error) {
setError(error);
} else {
setName('');
}
})
}

return (
<form action={submitAction}>
<input type="text" name="name" disabled={isPending}/>
{state.error && <span>Failed: {state.error}</span>}
</form>
)
}

透過在客戶端將伺服器函式包裝在一個 Action 中,您可以訪問伺服器函式的 isPending 狀態。

更多資訊,請參閱關於 <form> 之外呼叫伺服器函式 的文件。

具有表單動作的伺服器函式

伺服器函式可與 React 19 中新的表單功能搭配使用。

您可以將伺服器函式傳遞給表單,以自動將表單提交到伺服器。

"use client";

import {updateName} from './actions';

function UpdateName() {
return (
<form action={updateName}>
<input type="text" name="name" />
</form>
)
}

當表單提交成功時,React 會自動重設表單。您可以新增 useActionState 來訪問處理中狀態、最後的回應,或支援漸進式增強。

更多資訊,請參閱關於 表單中的伺服器函式 的文件。

使用 useActionState 的伺服器函式

在只需要訪問動作處理中狀態和最後返回的回應的常見情況下,您可以使用 useActionState 來呼叫伺服器函式。

"use client";

import {updateName} from './actions';

function UpdateName() {
const [state, submitAction, isPending] = useActionState(updateName, {error: null});

return (
<form action={submitAction}>
<input type="text" name="name" disabled={isPending}/>
{state.error && <span>Failed: {state.error}</span>}
</form>
);
}

當將 useActionState 與伺服器函式一起使用時,React 還會自動重播在水合完成之前輸入的表單提交。這表示使用者即使在應用程式水合之前也可以與您的應用程式互動。

更多資訊,請參閱關於 useActionState 的文件。

使用 useActionState 漸進式增強

伺服器函式也支援使用 useActionState 的第三個參數進行漸進式增強。

"use client";

import {updateName} from './actions';

function UpdateName() {
const [, submitAction] = useActionState(updateName, null, `/name/update`);

return (
<form action={submitAction}>
...
</form>
);
}

永久連結 提供給 useActionState 時,如果在 JavaScript 程式碼載入之前提交表單,React 將會重新導向到提供的網址。

更多資訊,請參閱關於 useActionState 的文件。