禁用查询

禁用/暂停查询

如果你希望禁用某个查询,使其不会自动运行,可以使用 enabled = false 选项。enabled 选项也可以接收一个返回布尔值的函数。

enabledfalse 时:

  • 如果查询已有缓存数据,则查询将以 status === 'success'isSuccess 状态初始化。

  • 如果查询没有缓存数据,则查询将以 status === 'pending'fetchStatus === 'idle' 状态开始。

  • 查询在挂载时不会自动获取数据。

  • 查询不会在后台自动重新获取数据。

  • 查询将忽略查询客户端的 invalidateQueriesrefetchQueries 调用,这些调用通常会导致查询重新获取。

  • 可以使用 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)

延迟查询从一开始就会处于 status: 'pending' 状态,因为 pending 意味着还没有数据。这在技术上是正确的,但由于我们当前没有获取任何数据(因为查询未被启用),这意味着你可能无法使用此标志来显示加载指示器。

如果你使用的是禁用或延迟查询,可以使用 isLoading 标志。它是一个派生标志,其计算方式为:

isPending && isFetching

因此,只有当查询正在首次获取数据时,它才会为 true

使用 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>
  )
}

最后更新于

这有帮助吗?