后端的力量,前端的体验:React Router Server Action 的魔力

解读 React Router Server Action

这段代码与之前的 clientAction 非常相似,但有一个核心区别:数据处理逻辑在服务器端执行。这为处理需要安全验证或直接访问数据库等敏感操作提供了保障。

我们同样分两部分来看:action 函数和 Project 组件。

Server action 函数

这个 action 函数被设计为只在服务器上运行。当表单被提交时,React Router 会将请求发送到你的服务器,并由服务器执行这个函数。

jsx 复制代码
// 这个函数只在服务器上运行
// 它不会被打包进发送给浏览器的 JavaScript 文件中
export async function action({
  request,
}: Route.ActionArgs) {
  // 1. 在服务器上获取表单数据
  let formData = await request.formData();
  let title = formData.get("title");

  // 2. 在服务器上直接与数据库交互
  let project = await fakeDb.updateProject({ title });

  // 3. 从服务器返回更新后的数据
  return project;
}

代码分步解析:

  1. await request.formData() : 当用户提交表单后,React Router 会向当前页面的 URL 发送一个 POST 请求。服务器接收到这个请求,这里的代码在服务器环境中解析出表单数据。
  2. await fakeDb.updateProject({ title }) : 这是最关键的一步。因为这段代码在服务器上运行,所以它可以安全地导入并调用服务器端的模块,比如直接操作数据库的 fakeDb。这些敏感的数据库操作逻辑永远不会暴露给用户的浏览器。
  3. return project : 函数执行完毕后,会将 project 数据序列化(通常是转为 JSON),并通过网络响应发送回用户的浏览器。

核心优势

  • 安全性:数据库凭证、私有 API 密钥和核心业务逻辑都保留在服务器上,永远不会发送到客户端,极大地提高了应用的安全性。
  • 代码分离action 函数及其依赖(如 fakeDb)会自动从客户端的 JavaScript 包中移除,减小了浏览器需要下载的文件体积,提升了加载性能。

Project 组件

组件部分的代码与 clientAction 的例子完全一样,但这正是 React Router 设计的巧妙之处。作为开发者,你不需要改变组件的写法,框架会自动处理数据是通过客户端还是服务器端提交的。

jsx 复制代码
export default function Project({
  actionData,
}: Route.ComponentProps) {
  return (
    <div>
      <h1>Project</h1>
      {/* A. <Form> 的行为发生了变化 */}
      <Form method="post">
        <input type="text" name="title" />
        <button type="submit">Submit</button>
      </Form>
      
      {/* B. 同样接收 action 的返回值并更新 UI */}
      {actionData ? (
        <p>{actionData.title} updated</p>
      ) : null}
    </div>
  );
}

代码分步解析:

A. <Form method="post"> : 在这个场景下,React Router 的 <Form> 组件的行为是:

  • 拦截用户的提交事件,阻止页面刷新。
  • 创建一个标准的 POST 网络请求,将表单数据发送到当前页面的 URL。
  • 等待服务器的响应。

B. actionData Prop : 这个 prop 的数据来源变了。它现在接收的是从服务器 响应中返回的数据。当表单提交、服务器上的 action 函数成功执行并返回数据后,React Router 会捕获这个响应,并将数据通过 actionData prop 传递给组件,从而触发 UI 更新。

总结整个流程

这个 Server Action 的流程涉及一次完整的客户端-服务器通信:

  1. 用户操作:用户在浏览器中输入标题并点击 "Submit"。
  2. 网络请求 :React Router 的 <Form> 组件将表单数据打包,向服务器发起一个 POST 请求。
  3. 服务器处理 :服务器接收到请求,调用与该路由匹配的 action 函数。
  4. 数据变更action 函数在服务器上安全地执行数据库更新操作。
  5. 网络响应action 函数将更新后的 project 对象作为响应返回给浏览器。
  6. UI 更新 :在浏览器端,React Router 接收到这个响应数据,并将其注入到 Project 组件的 actionData prop 中。
  7. 显示反馈 :组件因 actionData 变化而重新渲染,无缝地向用户展示更新成功的消息。

对比 clientAction 与 Server action

  • clientAction:在浏览器中运行,适合执行纯客户端逻辑,如调用公开的第三方 API 或在发送前进行数据校验。反馈更快,因为它不涉及网络往返。
  • Server action:在服务器上运行,是处理需要保护的业务逻辑或直接操作后端资源的理想选择。它更安全、更强大。

React Router 允许你在同一个路由中同时定义 clientActionaction。在这种情况下,clientAction 会优先执行,这为你实现更复杂的交互模式(如乐观更新)提供了可能。

相关推荐
前端工作日常3 小时前
我理解的`npm pack` 和 `npm install <local-path>`
前端
李剑一3 小时前
说个多年老前端都不知道的标签正确玩法——q标签
前端
嘉小华3 小时前
大白话讲解 Android屏幕适配相关概念(dp、px 和 dpi)
前端
姑苏洛言4 小时前
在开发跑腿小程序集成地图时,遇到的坑,MapContext.includePoints(Object object)接口无效在组件中使用无效?
前端
奇舞精选4 小时前
Prompt 工程实用技巧:掌握高效 AI 交互核心
前端·openai
Danny_FD4 小时前
React中可有可无的优化-对象类型的使用
前端·javascript
用户757582318554 小时前
混合应用开发:企业降本增效之道——面向2025年移动应用开发趋势的实践路径
前端
P1erce4 小时前
记一次微信小程序分包经历
前端
LeeAt4 小时前
从Promise到async/await的逻辑演进
前端·javascript
等一个晴天丶4 小时前
不一样的 TypeScript 入门手册
前端