禁用/暂停查询
如果你希望禁用某个查询,使其不会自动运行,可以使用 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),
// ⬇️ 当筛选条件为空时禁用
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],
// ⬇️ 当筛选条件为 undefined 或为空时禁用
queryFn: filter ? () => fetchTodos(filter) : skipToken,
})
return (
<div>
// 🚀 应用筛选条件将启用并执行查询
<FiltersForm onApply={setFilter} />
{data && <TodosTable data={data} />}
</div>
)
}最后更新于
这有帮助吗?