框架
版本

禁用/暂停查询

如果您想禁用查询自动运行,可以使用 enabled = false 选项。enabled 选项也接受一个返回布尔值的回调函数。

enabledfalse

  • 如果查询有缓存数据,则查询将以 status === 'success'isSuccess 状态初始化。
  • 如果查询没有缓存数据,则查询将以 status === 'pending'fetchStatus === 'idle' 状态开始。
  • 查询不会在挂载时自动获取。
  • 查询不会在后台自动重新获取。
  • 查询将忽略通常会导致查询重新获取的查询客户端 invalidateQueriesrefetchQueries 调用。
  • useQuery 返回的 refetch 可用于手动触发查询获取。但是,它不适用于 skipToken

TypeScript 用户可能更喜欢使用 skipToken 作为 enabled = false 的替代方案。

tsx
function Todos() {
  const { isLoading, isError, data, error, refetch, isFetching } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodoList,
    enabled: false,
  })

  return (
    <div>
      <button onClick={() => refetch()}>Fetch Todos</button>

      {data ? (
        <ul>
          {data.map((todo) => (
            <li key={todo.id}>{todo.title}</li>
          ))}
        </ul>
      ) : isError ? (
        <span>Error: {error.message}</span>
      ) : isLoading ? (
        <span>Loading...</span>
      ) : (
        <span>Not ready ...</span>
      )}

      <div>{isFetching ? 'Fetching...' : null}</div>
    </div>
  )
}
function Todos() {
  const { isLoading, isError, data, error, refetch, isFetching } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodoList,
    enabled: false,
  })

  return (
    <div>
      <button onClick={() => refetch()}>Fetch Todos</button>

      {data ? (
        <ul>
          {data.map((todo) => (
            <li key={todo.id}>{todo.title}</li>
          ))}
        </ul>
      ) : isError ? (
        <span>Error: {error.message}</span>
      ) : isLoading ? (
        <span>Loading...</span>
      ) : (
        <span>Not ready ...</span>
      )}

      <div>{isFetching ? 'Fetching...' : null}</div>
    </div>
  )
}

永久禁用查询会放弃 TanStack Query 提供的许多出色功能(例如后台重新获取),而且它也不是惯用的方法。它将您从声明性方法(定义查询何时运行的依赖项)带入命令式模式(每当我点击这里时就获取)。也不可能向 refetch 传递参数。通常,您想要的只是一个延迟初始获取的惰性查询。

惰性查询

enabled 选项不仅可以用于永久禁用查询,还可以用于在稍后时间启用/禁用它。一个很好的例子是筛选表单,您只想在用户输入筛选值后才触发第一个请求。

tsx
function Todos() {
  const [filter, setFilter] = React.useState('')

  const { data } = useQuery({
    queryKey: ['todos', filter],
    queryFn: () => fetchTodos(filter),
    // ⬇️ disabled as long as the filter is empty
    enabled: !!filter,
  })

  return (
    <div>
      // 🚀 applying the filter will enable and execute the query
      <FiltersForm onApply={setFilter} />
      {data && <TodosTable data={data} />}
    </div>
  )
}
function Todos() {
  const [filter, setFilter] = React.useState('')

  const { data } = useQuery({
    queryKey: ['todos', filter],
    queryFn: () => fetchTodos(filter),
    // ⬇️ disabled as long as the filter is empty
    enabled: !!filter,
  })

  return (
    <div>
      // 🚀 applying the filter will enable and execute the query
      <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 相同。

tsx
import { skipToken, useQuery } from '@tanstack/react-query'

function Todos() {
  const [filter, setFilter] = React.useState<string | undefined>()

  const { data } = useQuery({
    queryKey: ['todos', filter],
    // ⬇️ disabled as long as the filter is undefined or empty
    queryFn: filter ? () => fetchTodos(filter) : skipToken,
  })

  return (
    <div>
      // 🚀 applying the filter will enable and execute the query
      <FiltersForm onApply={setFilter} />
      {data && <TodosTable data={data} />}
    </div>
  )
}
import { skipToken, useQuery } from '@tanstack/react-query'

function Todos() {
  const [filter, setFilter] = React.useState<string | undefined>()

  const { data } = useQuery({
    queryKey: ['todos', filter],
    // ⬇️ disabled as long as the filter is undefined or empty
    queryFn: filter ? () => fetchTodos(filter) : skipToken,
  })

  return (
    <div>
      // 🚀 applying the filter will enable and execute the query
      <FiltersForm onApply={setFilter} />
      {data && <TodosTable data={data} />}
    </div>
  )
}