等待查询过期后才再次获取并不总是有效,尤其是在您确切知道由于用户执行了某些操作而导致查询数据已过期时。为此,QueryClient 提供了一个 invalidateQueries 方法,可让您智能地将查询标记为过时,并可能也重新获取它们!
// 使缓存中的每个查询失效
queryClient.invalidateQueries()
// 使键以 `todos` 开头的每个查询失效
queryClient.invalidateQueries({ queryKey: ['todos'] })
// 使缓存中的每个查询失效
queryClient.invalidateQueries()
// 使键以 `todos` 开头的每个查询失效
queryClient.invalidateQueries({ queryKey: ['todos'] })
注意:其他使用规范化缓存的库会尝试通过命令式或模式推断来更新本地查询中的新数据,而 TanStack Query 为您提供了避免维护规范化缓存所需的手动工作的工具,而是规定了有针对性的失效、后台重新获取并最终实现原子更新。
当使用 invalidateQueries 使查询失效时,会发生两件事:
当使用诸如 invalidateQueries 和 removeQueries(以及其他支持部分查询匹配的 API)之类的 API 时,您可以按其前缀匹配多个查询,或者非常具体地匹配确切的查询。有关可以使用的过滤器类型的信息,请参阅查询过滤器。
在此示例中,我们可以使用 todos 前缀来使查询键中以 todos 开头的任何查询失效:
import { useQuery, useQueryClient } from '@tanstack/react-query'
// 从上下文中获取 QueryClient
const queryClient = useQueryClient()
queryClient.invalidateQueries({ queryKey: ['todos'] })
// 以下两个查询都将失效
const todoListQuery = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
const todoListQuery = useQuery({
queryKey: ['todos', { page: 1 }],
queryFn: fetchTodoList,
})
import { useQuery, useQueryClient } from '@tanstack/react-query'
// 从上下文中获取 QueryClient
const queryClient = useQueryClient()
queryClient.invalidateQueries({ queryKey: ['todos'] })
// 以下两个查询都将失效
const todoListQuery = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
const todoListQuery = useQuery({
queryKey: ['todos', { page: 1 }],
queryFn: fetchTodoList,
})
您甚至可以通过将更具体的查询键传递给 invalidateQueries 方法来使具有特定变量的查询失效:
queryClient.invalidateQueries({
queryKey: ['todos', { type: 'done' }],
})
// 以下查询将被失效
const todoListQuery = useQuery({
queryKey: ['todos', { type: 'done' }],
queryFn: fetchTodoList,
})
// 但是,以下查询将不会被失效
const todoListQuery = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
queryClient.invalidateQueries({
queryKey: ['todos', { type: 'done' }],
})
// 以下查询将被失效
const todoListQuery = useQuery({
queryKey: ['todos', { type: 'done' }],
queryFn: fetchTodoList,
})
// 但是,以下查询将不会被失效
const todoListQuery = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
invalidateQueries API 非常灵活,因此即使您只想仅使没有任何其他变量或子键的 todos 查询失效,也可以将 exact: true 选项传递给 invalidateQueries 方法:
queryClient.invalidateQueries({
queryKey: ['todos'],
exact: true,
})
// 以下查询将被失效
const todoListQuery = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
// 但是,以下查询将不会被失效
const todoListQuery = useQuery({
queryKey: ['todos', { type: 'done' }],
queryFn: fetchTodoList,
})
queryClient.invalidateQueries({
queryKey: ['todos'],
exact: true,
})
// 以下查询将被失效
const todoListQuery = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
// 但是,以下查询将不会被失效
const todoListQuery = useQuery({
queryKey: ['todos', { type: 'done' }],
queryFn: fetchTodoList,
})
如果您发现自己想要甚至更精细的控制,可以将谓词函数传递给 invalidateQueries 方法。此函数将从查询缓存中接收每个 Query 实例,并允许您返回 true 或 false 以指示是否要使该查询失效:
queryClient.invalidateQueries({
predicate: (query) =>
query.queryKey[0] === 'todos' && query.queryKey[1]?.version >= 10,
})
// 以下查询将被失效
const todoListQuery = useQuery({
queryKey: ['todos', { version: 20 }],
queryFn: fetchTodoList,
})
// 以下查询将被失效
const todoListQuery = useQuery({
queryKey: ['todos', { version: 10 }],
queryFn: fetchTodoList,
})
// 但是,以下查询将不会被失效
const todoListQuery = useQuery({
queryKey: ['todos', { version: 5 }],
queryFn: fetchTodoList,
})
queryClient.invalidateQueries({
predicate: (query) =>
query.queryKey[0] === 'todos' && query.queryKey[1]?.version >= 10,
})
// 以下查询将被失效
const todoListQuery = useQuery({
queryKey: ['todos', { version: 20 }],
queryFn: fetchTodoList,
})
// 以下查询将被失效
const todoListQuery = useQuery({
queryKey: ['todos', { version: 10 }],
queryFn: fetchTodoList,
})
// 但是,以下查询将不会被失效
const todoListQuery = useQuery({
queryKey: ['todos', { version: 5 }],
queryFn: fetchTodoList,
})