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 的 json
、reload
或 redirect
助手返回响应,你可以将键/键组传递给 json 响应助手的第二个参数中的 revalidate 属性。
你可以直接传递 string
,或使用缓存函数的 key
或 keyFor
属性。
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)); });
// ...}