查询失效处理
等待查询过期后再重新拉取数据并不总是可行,尤其是当你明确知道某个查询的数据已因用户操作而过时。为此,QueryClient 提供了 invalidateQueries 方法,让你能够智能地标记查询为过期,并可选择同时重新拉取它们!
TypeScript
1// Invalidate every query in the cache2queryClient.invalidateQueries()3// Invalidate every query with a key that starts with `todos`4queryClient.invalidateQueries({ queryKey: ['todos'] })注意:其他使用规范化缓存(normalized cache)的库通常会尝试通过命令式方式或基于模式推断来更新本地查询中的数据;而 TanStack Query 则为你提供工具,以避免维护规范化缓存所带来的手动工作,转而推荐采用 精准失效处理、后台重新拉取以及最终的原子更新。
当使用 invalidateQueries 使一个查询失效时,会发生两件事:
- 该查询被标记为过期。此过期状态会覆盖
useQuery或相关 Hook 中配置的任何staleTime设置。 - 如果该查询当前正通过
useQuery或相关 Hook 渲染,则它还会在后台被重新拉取。
使用 invalidateQueries 进行查询匹配
在使用 invalidateQueries 和 removeQueries(以及其他支持部分查询匹配的 API)时,你可以通过前缀匹配多个查询,也可以精确匹配某个特定查询。有关可用筛选器类型的详细信息,请参阅 查询筛选器。
在本示例中,我们可以使用 todos 前缀来使所有查询键以 todos 开头的查询失效:
TypeScript
1import { useQuery, useQueryClient } from '@tanstack/vue-query'2 3// Get QueryClient from the context4const queryClient = useQueryClient()5 6queryClient.invalidateQueries({ queryKey: ['todos'] })7 8// Both queries below will be invalidated9const todoListQuery = useQuery({10 queryKey: ['todos'],11 queryFn: fetchTodoList,12})13const todoListQuery = useQuery({14 queryKey: ['todos', { page: 1 }],15 queryFn: fetchTodoList,16})你甚至可以通过向 invalidateQueries 方法传入更具体的查询键,来使带有特定变量的查询失效:
TypeScript
1queryClient.invalidateQueries({2 queryKey: ['todos', { type: 'done' }],3})4 5// The query below will be invalidated6const todoListQuery = useQuery({7 queryKey: ['todos', { type: 'done' }],8 queryFn: fetchTodoList,9})10 11// However, the following query below will NOT be invalidated12const todoListQuery = useQuery({13 queryKey: ['todos'],14 queryFn: fetchTodoList,15})invalidateQueries API 非常灵活:即使你只想使那些查询键恰好等于 todos(即不带任何额外变量或子键)的查询失效,也可以向 invalidateQueries 方法传入一个 exact: true 选项:
TypeScript
1queryClient.invalidateQueries({2 queryKey: ['todos'],3 exact: true,4})5 6// The query below will be invalidated7const todoListQuery = useQuery({8 queryKey: ['todos'],9 queryFn: fetchTodoList,10})11 12// However, the following query below will NOT be invalidated13const todoListQuery = useQuery({14 queryKey: ['todos', { type: 'done' }],15 queryFn: fetchTodoList,16})如果你需要 更精细 的控制,还可以向 invalidateQueries 方法传入一个谓词函数。该函数将接收查询缓存中的每个 Query 实例,并允许你返回 true 或 false,以决定是否使该查询失效:
TypeScript
1queryClient.invalidateQueries({2 predicate: (query) =>3 query.queryKey[0] === 'todos' && query.queryKey[1]?.version >= 10,4})5 6// The query below will be invalidated7const todoListQuery = useQuery({8 queryKey: ['todos', { version: 20 }],9 queryFn: fetchTodoList,10})11 12// The query below will be invalidated13const todoListQuery = useQuery({14 queryKey: ['todos', { version: 10 }],15 queryFn: fetchTodoList,16})17 18// However, the following query below will NOT be invalidated19const todoListQuery = useQuery({20 queryKey: ['todos', { version: 5 }],21 queryFn: fetchTodoList,22})