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

来自修改响应的更新

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

处理那些在服务端 更新 对象的修改时,新对象通常会自动作为修改响应的一部分返回。此时,你无需重新拉取与该对象相关的任何查询(那样会浪费一次网络请求,而我们本已拥有这些数据),而是可以直接利用修改函数返回的对象,立即通过 Query Client 的 setQueryData 方法更新现有查询:

TypeScript
1const queryClient = useQueryClient()2 3const mutation = useMutation({4  mutationFn: editTodo,5  onSuccess: (data) => {6    queryClient.setQueryData(['todo', { id: 5 }], data)7  },8})9 10mutation.mutate({11  id: 5,12  name: 'Do the laundry',13})14 15// The query below will be updated with the response from the16// successful mutation17const { status, data, error } = useQuery({18  queryKey: ['todo', { id: 5 }],19  queryFn: fetchTodoById,20})

你可能希望将 onSuccess 逻辑封装进一个可复用的修改中,为此你可以创建如下自定义 Hook:

TypeScript
1const useMutateTodo = () => {2  const queryClient = useQueryClient()3 4  return useMutation({5    mutationFn: editTodo,6    // Notice the second argument is the variables object that the `mutate` function receives7    onSuccess: (data, variables) => {8      queryClient.setQueryData(['todo', { id: variables.id }], data)9    },10  })11}

不可变性

通过 setQueryData 进行的更新必须以 不可变 的方式进行。切勿尝试直接修改缓存中的数据(例如就地修改从缓存中获取的数据)来写入缓存。这种方式或许起初看似可行,但最终可能导致难以察觉的 bug。

TypeScript
1queryClient.setQueryData(['posts', { id }], (oldData) => {2  if (oldData) {3    // ❌ do not try this4    oldData.title = 'my new post title'5  }6  return oldData7})8 9queryClient.setQueryData(10  ['posts', { id }],11  // ✅ this is the way12  (oldData) =>13    oldData14      ? {15          ...oldData,16          title: 'my new post title',17        }18      : oldData,19)

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

译自上游 59d11de