修改
与查询不同,修改用于创建、更新、删除或以其他方式执行服务端副作用(server side effects)。在 Lit 中,请使用 createMutationController。
TypeScript
1import { LitElement, html } from 'lit'2import {3 QueryClient,4 QueryClientProvider,5 createMutationController,6 createQueryController,7} from '@tanstack/lit-query'8 9const queryClient = new QueryClient()10 11class AppQueryProvider extends QueryClientProvider {12 constructor() {13 super()14 this.client = queryClient15 }16}17 18customElements.define('app-query-provider', AppQueryProvider)19 20class TodosView extends LitElement {21 private readonly todos = createQueryController(this, {22 queryKey: ['todos'],23 queryFn: fetchTodos,24 })25 26 private readonly addTodo = createMutationController(this, {27 mutationFn: createTodo,28 onSuccess: async () => {29 await queryClient.invalidateQueries({ queryKey: ['todos'] })30 },31 })32 33 render() {34 const query = this.todos()35 const mutation = this.addTodo()36 const todos = query.data ?? []37 38 return html`39 ${mutation.isError ? html`<p>${mutation.error.message}</p>` : null}40 ${mutation.isSuccess ? html`<p>Todo added</p>` : null}4142 <button43 ?disabled=${mutation.isPending}44 @click=${() => this.addTodo.mutate({ title: 'Write mutation docs' })}45 >46 ${mutation.isPending ? 'Adding...' : 'Add Todo'}47 </button>4849 <ul>50 ${todos.map((todo) => html`<li>${todo.title}</li>`)}51 </ul>52 `53 }54}55 56customElements.define('todos-view', TodosView)将元素渲染在提供者(provider)之下,以便控制器能从 Lit 上下文解析出相同的 QueryClient:
HTML
1<app-query-provider>2 <todos-view></todos-view>3</app-query-provider>修改状态
一个修改可能处于以下主要状态之一:
isIdle或status === 'idle':尚未运行任何修改,或已重置isPending或status === 'pending':修改正在运行中isError或status === 'error':修改失败,且error可用isSuccess或status === 'success':修改已完成,且data可用
变量
通过调用 mutate 向修改函数传入变量:
TypeScript
1this.addTodo.mutate({2 title: this.nextTitle,3})若控制器无法解析 QueryClient(例如元素未渲染在已连接的 QueryClientProvider 下,且未显式传入 client),则 mutate 会同步抛出异常。mutateAsync 将同样的配置问题报告为一个被拒绝的 Promise。
当你需要 Promise 时,请使用 mutateAsync:
TypeScript
1try {2 const created = await this.addTodo.mutateAsync({ title: this.nextTitle })3 this.nextTitle = created.title4} catch (error) {5 this.errorMessage = String(error)6}重置修改状态
访问器包含 reset:
TypeScript
1html`2 ${3 mutation.isError4 ? html`<button @click=${() => this.addTodo.reset()}>Clear error</button>`5 : null6 }7`副作用
修改选项支持 onMutate、onError、onSuccess 和 onSettled。分页示例向控制器显式传入 queryClient,并在乐观更新与回滚中复用同一作用域内的 client。其 mutationKey 和 mutationFn 来自该示例的 projectsMutations.updateFavorite():
TypeScript
1private readonly favoriteMutation = createMutationController(2 this,3 {4 ...projectsMutations.updateFavorite(),5 onMutate: async (variables) => {6 await queryClient.cancelQueries({ queryKey: projectsQueries.all() })7 const snapshots = queryClient.getQueriesData<ProjectsPageResponse>({8 queryKey: projectsQueries.all(),9 })10 11 for (const [key, existing] of snapshots) {12 if (!existing) continue13 14 queryClient.setQueryData<ProjectsPageResponse>(key, {15 ...existing,16 projects: existing.projects.map((project) =>17 project.id === variables.id18 ? { ...project, isFavorite: variables.isFavorite }19 : project,20 ),21 })22 }23 24 return { snapshots }25 },26 onError: (_error, _variables, onMutateResult) => {27 for (const [key, snapshot] of onMutateResult?.snapshots ?? []) {28 queryClient.setQueryData(key, snapshot)29 }30 },31 onSettled: async () => {32 await queryClient.invalidateQueries({ queryKey: projectsQueries.all() })33 },34 },35 queryClient,36)如需查看精确可运行的完整流程,请参阅 分页示例。