Concepts

Actions

编辑此页面

在开发应用程序时,经常需要根据用户交互向服务器传递新信息。Action 是 Solid Router 针对这个问题的解决方案。


什么是 action?

Action 是异步处理函数,允许你向服务器提交数据并接收响应。它们是同构的,意味着可以根据需要在服务器或客户端上运行。这种灵活性使 action 成为管理和跟踪数据提交的强大工具。

action 的工作原理

Action 代表 HTML 表单的服务器端部分。它们通过 POST 请求处理提交,使你能够轻松使用 HTML 表单发送数据。

当用户执行操作(如提交表单)时,数据会通过 action 发送到服务器进行处理。

使用 action 的好处

  1. 同构性: 由于 action 可以在服务器和客户端上运行,你可以通过选择最佳执行环境来优化性能。
  2. 异步处理: action 异步处理数据提交,确保应用程序保持响应。
  3. 简化数据处理: 使用 action,可以简化数据提交的管理和跟踪过程,降低应用程序的复杂性。

创建 action

要创建 action,请使用 action 函数,该函数来自 @solidjs/router 包。此函数接收一个异步函数作为参数,并返回一个可用于提交数据的新函数。

import { action } from "@solidjs/router";
const echo = action(async (message: string) => {
// Simulates an asynchronous operation, such as an API call
await new Promise((resolve, reject) => setTimeout(resolve, 1000));
console.log(message);
});

在这个例子中,echo acton 模拟了一个 fetch 调用,在将消息记录到控制台之前有 1 秒的延迟。echo action 将作为后端,但是,它可以替换为任何可以在客户端运行的 API。通常,路由 actions 与 fetch 或GraphQL 等解决方案一起使用。

使用 actions

To use the action, you can call it from within a component using useAction. This returns a function that can be called with the necessary arguments to trigger the action.

要使用该 action,你可以在组件中使用 useAction 来调用它。这会返回一个可以调用的函数来触发此action。

import { action } from "@solidjs/router";
import { action, useAction } from "@solidjs/router";
const echo = action(async (message: string) => {
await new Promise((resolve, reject) => setTimeout(resolve, 1000));
console.log(message);
});
export function MyComponent() {
const myEcho = useAction(echo);
myEcho("Hello from Solid!");
}

在这个组件中,useAction 用于获取对 echo action 的引用。然后使用消息 "Hello from Solid!" 调用该action,该消息将在 1 秒延迟后记录到控制台。

从 actions 返回数据

在许多情况下,提交数据后,服务器也会返回一些数据。可能是成功操作的结果,也可能是操作失败时返回的错误消息。

从 action 返回的任何内容都可以使用响应式 action.result 属性访问,每次提交 action 时该值都可能发生变化。

要访问 action 的结果,你必须将 action 传递给 useSubmission

import { action, useAction } from "@solidjs/router";
import { action, useAction, useSubmission } from "@solidjs/router";
const echo = action(async (message: string) => {
await new Promise((resolve, reject) => setTimeout(resolve, 1000));
return message;
});
export function MyComponent() {
const myEcho = useAction(echo);
const echoing = useSubmission(echo);
myEcho("Hello from solid!");
setTimeout(() => myEcho("This is a second submission!"), 1500);
return <p>{echoing.result}</p>;
}

Using useSubmission leaves the implementation details of how you trigger echo up to you. When handling user inputs, for example, it is better to use a form for a multitude of reasons.

使用 useSubmission 可以让你可以自行决定如何触发 echo。在处理用户输入时,出于多种原因,使用 form 会更好。


使用表单提交数据

在使用 actions 提交数据时,建议使用 HTML 表单。这些表单可以在 JavaScript 加载之前使用,从而创建即时交互的应用程序。这也天然提供了无障碍性优势,省去了设计可能没有这些优势的自定义 UI 库的时间。

当使用表单提交 actions 时,传递给 action 函数的第一个参数是 FormData 实例。要在表单中使用 actions,请将 actions 传递给表单的 action 属性。这将创建渐进增强的表单,即使在禁用 JavaScript 的情况下也能工作。

如果你不从 action 中返回一个 Response,用户将停留在同一页面,响应将被重新触发。使用 redirect 可以告诉浏览器导航到新页面。

import { action, redirect } from "@solidjs/router";
const isAdmin = action(async (formData: FormData) => {
await new Promise((resolve, reject) => setTimeout(resolve, 1000));
const username = formData.get("username");
if (username === "admin") throw redirect("/admin");
return new Error("Invalid username");
});
export function MyComponent() {
return (
<form action={isAdmin} method="post">
<label for="username">Username:</label>
<input type="text" name="username" />
<input type="submit" value="submit" />
</form>
);
}

注意: 如果您要上传文件,请确保在<form> 元素中包含 enctype="multipart/form-data"


错误处理

建议从 actions 中返回错误而不是抛出错误。这有助于对与 useSubmission 一起使用的提交进行类型处理。这在处理无 JavaScript 客户端的渐进增强时很重要,这样错误就可以声明式地用于在服务器上渲染更新后的页面。

此外,在使用 server actions 时,在服务器端处理错误以净化错误消息是一个好的做法。

报告此页面问题