React Server Actions入门

472 阅读1分钟

Untitled.png

React Server Actions的简介

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

Server Actions 主要有如下优点:

  • 简化数据获取逻辑:直接在服务器端获取数据并传递给组件,简化了数据获取逻辑。不需要在客户端编写 API 请求逻辑。
  • 渐进式增强表单:Server Action 可以与 useActionState Hooks结合使用,支持渐进式增强表单功能。

使用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);
	}
// 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或者其他效果。

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

// actions.js
"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>
  );
}