译零 TransZero · TanStack Query 中文文档
主站

修改

更新于 2026-11-02 Lit 查看英文原文 ↗

与查询不同,修改用于创建、更新、删除或以其他方式执行服务端副作用(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)

如需查看精确可运行的完整流程,请参阅 分页示例。

本页为 TanStack Query 文档(Lit 版)的非官方中文翻译,原文由上游团队维护,遵循 MIT 许可。 译文如有偏差,以英文原文为准。

译自上游 59d11de