React Server Actions简介
2024/07/07
React Server Actions的简介
React Server Actions 是React 19中的一个新特性,能够在服务器上运行异步函数,可以在服务器组件和客户端组件中使用。
Server Actions 主要有如下优点:
- 简化数据获取逻辑:直接在服务器端获取数据并传递给组件,简化了数据获取逻辑。不需要在客户端编写 API 请求逻辑。
- 渐进式增强表单:Server Action 可以与
useActionState
Hooks结合使用,支持渐进式增强表单功能。
使用Server actions处理表单的提交
'use server';
export async function updateName(formData) { const username = formData.get('username'); if (!username) { return {error: 'username is required'}; } await db.users.updateName(username); }
// 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> );}