React Server Actions简介

2024/07/07

Untitled

React Server Actions的简介

React Server Actions 是React 19中的一个新特性,能够在服务器上运行异步函数,可以在服务器组件和客户端组件中使用。

Server Actions 主要有如下优点:

使用Server actions处理表单的提交

actions.js
'use server';
export async function updateName(formData) {
const username = formData.get('username');
if (!username) {
return {error: 'username is required'};
}
await db.users.updateName(username);
}
app.js
// Server Component
import { updateName } from './actions'
export default App() {
<form action={updateName}>
<input type="text" name="username" />
<button type="submit">Request</button>
</form>
}

上面示例中, requestUsername 是传递给 <form> 的Server Actions。当用户提交此表单时,会向服务端的 requestUsername 发起网络请求。当在表单中调用服务器操作时,React 将提供表单的 FormData 作为Server Actions函数的第一个参数。

表单之外的Server Actions

当在表单之外使用Server Action时,可以用startTransition Hooks调用Server Actions操作,根据isPending的状态显示loading或者其他效果。

以下是表单之外的服务器操作的示例:

"use server";
import { sql } from '@vercel/postgres';
export async function incrementLike() {
// 更新数据库
const result = await sql`UPDATE likes SET like_count = like_count + 1 RETURNING like_count`;
return result.rows[0].like_count;
}
"use client";
import incrementLike from "./actions";
import { useState, useTransition } from "react";
function LikeButton() {
const [isPending, startTransition] = useTransition();
const [likeCount, setLikeCount] = useState(0);
const onClick = () => {
startTransition(async () => {
const currentCount = await incrementLike();
setLikeCount(currentCount);
});
};
return (
<>
<p>Total Likes: {likeCount}</p>
<button onClick={onClick} disabled={isPending}>
{isPending ? 'Liking...' : 'Like'}
</button>;
</>
);
}

Server Actions 和 useActionState

对于只需要访问pending状态和response响应状态,可以使用 useActionState Hooks结合Server Actions一起使用:

"use client";
import { useActionState } from "react";
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>
);
}