框架
版本

查询

查询基础

查询是对绑定到**唯一键**的异步数据源的声明性依赖。查询可以与任何基于 Promise 的方法(包括 GET 和 POST 方法)一起使用,以从服务器获取数据。如果您的方法修改了服务器上的数据,我们建议改用突变(Mutations)

要在组件或自定义 Hook 中订阅查询,请调用 useQuery Hook,并至少传入:

  • **查询的唯一键**
  • 一个返回 Promise 的函数,该 Promise 会
    • 解析数据,或者
    • 抛出错误
tsx
import { useQuery } from '@tanstack/react-query'

function App() {
  const info = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
}
import { useQuery } from '@tanstack/react-query'

function App() {
  const info = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
}

您提供的**唯一键**在内部用于在整个应用程序中重新获取、缓存和共享您的查询。

useQuery 返回的查询结果包含您进行模板制作和数据其他用途所需的所有查询信息。

tsx
const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })

result 对象包含一些您需要了解才能高效工作的重要状态。查询在任何给定时刻只能处于以下状态之一:

  • isPendingstatus === 'pending' - 查询尚无数据
  • isErrorstatus === 'error' - 查询遇到错误
  • isSuccessstatus === 'success' - 查询成功且数据可用

除了这些主要状态之外,根据查询的状态,还可以获得更多信息:

  • error - 如果查询处于 isError 状态,则可以通过 error 属性获取错误。
  • data - 如果查询处于 isSuccess 状态,则可以通过 data 属性获取数据。
  • isFetching - 在任何状态下,如果查询正在获取(包括后台重新获取),则 isFetching 将为 true

对于**大多数**查询,通常只需检查 isPending 状态,然后是 isError 状态,最后假定数据可用并渲染成功状态即可。

tsx
function Todos() {
  const { isPending, isError, data, error } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodoList,
  })

  if (isPending) {
    return <span>Loading...</span>
  }

  if (isError) {
    return <span>Error: {error.message}</span>
  }

  // We can assume by this point that `isSuccess === true`
  return (
    <ul>
      {data.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  )
}
function Todos() {
  const { isPending, isError, data, error } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodoList,
  })

  if (isPending) {
    return <span>Loading...</span>
  }

  if (isError) {
    return <span>Error: {error.message}</span>
  }

  // We can assume by this point that `isSuccess === true`
  return (
    <ul>
      {data.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  )
}

如果您不喜欢布尔值,也可以随时使用 status 状态。

tsx
function Todos() {
  const { status, data, error } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodoList,
  })

  if (status === 'pending') {
    return <span>Loading...</span>
  }

  if (status === 'error') {
    return <span>Error: {error.message}</span>
  }

  // also status === 'success', but "else" logic works, too
  return (
    <ul>
      {data.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  )
}
function Todos() {
  const { status, data, error } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodoList,
  })

  if (status === 'pending') {
    return <span>Loading...</span>
  }

  if (status === 'error') {
    return <span>Error: {error.message}</span>
  }

  // also status === 'success', but "else" logic works, too
  return (
    <ul>
      {data.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  )
}

如果您在访问 data 之前检查了 pendingerror,TypeScript 也会正确收窄 data 的类型。

FetchStatus

除了 status 字段,您还将获得一个额外的 fetchStatus 属性,具有以下选项:

  • fetchStatus === 'fetching' - 查询当前正在获取。
  • fetchStatus === 'paused' - 查询想要获取,但它已暂停。有关更多信息,请参阅网络模式指南。
  • fetchStatus === 'idle' - 查询目前没有进行任何操作。

为什么有两种不同的状态?

后台重新获取和 stale-while-revalidate 逻辑使得 statusfetchStatus 的所有组合都成为可能。例如:

  • 处于 success 状态的查询通常处于 idle fetchStatus,但如果正在进行后台重新获取,它也可能处于 fetching 状态。
  • 一个挂载但没有数据的查询通常处于 pending 状态和 fetching fetchStatus,但如果没有网络连接,它也可能处于 paused 状态。

因此,请记住,查询可能处于 pending 状态,但实际上并没有获取数据。根据经验法则:

  • status 提供有关 data 的信息:我们是否有数据?
  • fetchStatus 提供有关 queryFn 的信息:它是否正在运行?

延伸阅读

有关执行状态检查的另一种方法,请参阅社区资源