禁用查询
禁用/暂停查询
如果你希望禁用某个查询,使其不会自动运行,可以使用 enabled = false 选项。enabled 选项也可以接收一个返回布尔值的函数。
当 enabled 为 false 时:
如果查询已有缓存数据,则查询将以
status === 'success'或isSuccess状态初始化。如果查询没有缓存数据,则查询将以
status === 'pending'和fetchStatus === 'idle'状态开始。查询在挂载时不会自动获取数据。
查询不会在后台自动重新获取数据。
查询将忽略查询客户端的
invalidateQueries和refetchQueries调用,这些调用通常会导致查询重新获取。可以使用
useQuery返回的refetch来手动触发查询获取。但是,它不能与skipToken一起使用。
TypeScript 用户 可能更倾向于使用 skipToken 作为
enabled = false的替代方案。
function Todos() {
const { isLoading, isError, data, error, refetch, isFetching } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
enabled: false,
})
return (
<div>
<button onClick={() => refetch()}>获取待办事项</button>
{data ? (
<ul>
{data.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
) : isError ? (
<span>错误: {error.message}</span>
) : isLoading ? (
<span>加载中...</span>
) : (
<span>未就绪 ...</span>
)}
<div>{isFetching ? '获取中...' : null}</div>
</div>
)
}永久禁用一个查询意味着你将无法使用 TanStack Query 提供的许多优秀功能(例如后台重新获取),而且这也不是推荐的编程方式。这会将你从声明式(定义查询何时应运行的依赖关系)转变为命令式(点击这里时才获取)。此外,你无法向 refetch 传递参数。通常,你真正需要的只是一个延迟加载的查询,即推迟首次获取:
延迟查询 (Lazy Queries)
enabled 选项不仅可以用来永久禁用查询,还可以用来在稍后的时间点启用或禁用它。一个很好的例子是一个过滤表单,你只想在用户输入了过滤值后才发起第一次请求:
function Todos() {
const [filter, setFilter] = React.useState('')
const { data } = useQuery({
queryKey: ['todos', filter],
queryFn: () => fetchTodos(filter),
// ⬇️ 当 filter 为空时禁用查询
enabled: !!filter,
})
return (
<div>
// 🚀 应用过滤器将启用并执行查询
<FiltersForm onApply={setFilter} />
{data && <TodosTable data={data} />}
</div>
)
}isLoading (之前: isInitialLoading)
isInitialLoading)延迟查询从一开始就会处于 status: 'pending' 状态,因为 pending 意味着还没有数据。这在技术上是正确的,但由于我们当前没有获取任何数据(因为查询未被启用),这意味着你可能无法使用此标志来显示加载指示器。
如果你使用的是禁用或延迟查询,可以使用 isLoading 标志。它是一个派生标志,其计算方式为:
isPending && isFetching
因此,只有当查询正在首次获取数据时,它才会为 true。
使用 skipToken 进行类型安全的查询禁用
skipToken 进行类型安全的查询禁用如果你使用的是 TypeScript,你可以使用 skipToken 来禁用一个查询。当你想根据某个条件禁用查询,但又希望查询保持类型安全时,这非常有用。
重要:
useQuery返回的refetch不能与skipToken一起使用。除此之外,skipToken的行为与enabled: false相同。
import { skipToken, useQuery } from '@tanstack/react-query'
function Todos() {
const [filter, setFilter] = React.useState<string | undefined>()
const { data } = useQuery({
queryKey: ['todos', filter],
// ⬇️ 当 filter 为 undefined 或为空时禁用查询
queryFn: filter ? () => fetchTodos(filter) : skipToken,
})
return (
<div>
// 🚀 应用过滤器将启用并执行查询
<FiltersForm onApply={setFilter} />
{data && <TodosTable data={data} />}
</div>
)
}最后更新于
这有帮助吗?