Data APIs

action

编辑此页面

Actions 是可以触发失效和进一步路由的数据变更操作。 以下是预构建的响应助手列表。

import { action, revalidate, redirect } from "@solidjs/router"
// 在任何地方
const myAction = action(async (data) => {
await doMutation(data);
throw redirect("/", { revalidate: getUser.keyFor(data.id) }); // 抛出响应以执行重定向
});
// 在组件中
<form action={myAction} method="post" />
// 或者
<button type="submit" formaction={myAction}></button>

Actions 只能与 post 请求一起使用。 这意味着表单需要设置 method="post"

当需要类型化数据时,可以使用 with 方法。 这样就不需要使用 FormData 或其他额外的隐藏字段。 with 方法的工作方式类似于 bind,按顺序应用参数。

不使用 with

const deleteTodo = action(async (formData: FormData) => {
const id = Number(formData.get("id"))
await api.deleteTodo(id)
})
<form action={deleteTodo} method="post">
<input type="hidden" name="id" value={todo.id} />
<button type="submit">删除</button>
</form>

使用 with

const deleteTodo = action(async (formData: FormData) => {
const id = Number(formData.get("id"))
await api.deleteTodo(id)
})
<form action={deleteTodo} method="post">
<input type="hidden" name="id" value={todo.id} />
<form action={deleteTodo.with(todo.id)} method="post">
<button type="submit">删除</button>
</form>

<form> 实现和 SSR 的注意事项

这需要稳定的引用,因为字符串只能作为属性序列化,这对于 SSR 的一致性至关重要,这些引用必须对齐。 解决方案是提供一个唯一的名称。

const myAction = action(async (args) => {}, "my-action");

useAction

除了表单外,actions 还可以直接包装在 useAction 原语中。 这就是路由上下文的创建方式。

// 在组件中
const submit = useAction(myAction);
submit(...args);

在表单上下文之外可以使用自定义数据而不是 formData。 这些助手保留类型。

然而,即使与服务器函数一起使用,例如与 SolidStart 一起使用时,这也需要客户端 JavaScript,并且不像表单那样具有渐进增强性。


useSubmission/useSubmissions

这些函数用于在进行中的操作期间合并乐观更新。 它们提供单个 Submission(最新的),或匹配的 Submissions 集合,可选择使用过滤函数。

type Submission<T, U> = {
input: T;
result: U;
error: any;
pending: boolean
clear: () => {}
retry: () => {}
}
const submissions = useSubmissions(action, (input) => filter(input));
const submission = useSubmission(action, (input) => filter(input));

重新验证缓存的函数

重新验证所有(默认)

默认情况下,无论 action 是否返回或返回"正常"响应,所有缓存的函数都将被重新验证。

const deleteTodo = action(async (formData: FormData) => {
const id = Number(formData.get("id"))
await api.deleteTodo(id)
// ...
return new Response("success", { status: 200 });
})

重新验证特定的缓存键

通过使用 solid-router 的 jsonreloadredirect 助手返回响应,你可以将键/键组传递给 json 响应助手的第二个参数中的 revalidate 属性。 你可以直接传递 string,或使用缓存函数的 keykeyFor 属性。

import { action, json, reload, redirect } from "@solidjs/router"
const deleteTodo = action(async (formData: FormData) => {
const id = Number(formData.get("id"))
await api.deleteTodo(id)
return json(
{ deleted: id },
{ revalidate: ["getAllTodos", getTodos.key, getTodoByID.keyFor(id)]}
)
// 或者
return reload({ revalidate: ["getAllTodos", getTodos.key, getTodoByID.keyFor(id)]})
// 或者
return redirect("/", { revalidate: ["getAllTodos", getTodos.key, getTodoByID.keyFor(id)]})
})

防止重新验证

要退出任何重新验证,你可以将任何不是缓存函数键的 string 传递给 revalidate。

const deleteTodo = action(async (formData: FormData) => {
const id = Number(formData.get("id"))
await api.deleteTodo(id)
// 返回 `json` 而不重新验证 action
return json(`deleted ${id}`,{ revalidate: "nothing" })
// 或者重新加载路由而不重新验证请求
return reload({ revalidate: "nothing" })
// 或者重定向而不重新验证
return redirect("/", { revalidate: "nothing" })
})

不使用 action 进行重新验证

缓存的函数也可以通过 revalidate 助手重新验证。

revalidate([getTodos.key, getTodoByID.keyFor(id)]);

如果你想设置自己的"刷新"间隔,例如每 30 秒轮询数据一次,这也很好用。

export default function TodoLayout() {
const todos = createAsync(() => getTodos());
onMount(() => {
// 30 秒轮询
const interval = setInterval(() => revalidate(getTodos.key), 1000 * 30);
onCleanup(() => clearInterval(interval));
});
// ...
}
报告此页面问题