依赖查询

依赖查询(也称为串行查询)是指一个查询需要等待前一个查询完成后才能执行。

useQuery 依赖查询

依赖查询的实现非常简单,只需使用 enabled 选项来告诉查询何时可以开始执行:

// 获取用户
const { data: user } = useQuery({
  queryKey: ['user', email],
  queryFn: getUserByEmail,
})

const userId = user?.id

// 然后获取该用户的项目
const {
  status,
  fetchStatus,
  data: projects,
} = useQuery({
  queryKey: ['projects', userId],
  queryFn: getProjectsByUser,
  // 仅当 userId 存在时,此查询才会执行
  enabled: !!userId,
})

projects 查询初始状态为:

status: 'pending'
isPending: true
fetchStatus: 'idle'

一旦 user 数据可用,projects 查询的 enabled 条件即满足,状态将变为:

status: 'pending'
isPending: true
fetchStatus: 'fetching'

获取到项目数据后,最终状态为:

status: 'success'
isPending: false
fetchStatus: 'idle'

useQueries 依赖查询

动态并行查询 useQueries 也可以依赖于前一个查询的结果,实现方式如下:

// 获取用户 ID 列表
const { data: userIds } = useQuery({
  queryKey: ['users'],
  queryFn: getUsersData,
  select: (users) => users.map((user) => user.id),
})

// 然后获取每个用户的消息
const usersMessages = useQueries({
  queries: userIds
    ? userIds.map((id) => {
        return {
          queryKey: ['messages', id],
          queryFn: () => getMessagesByUsers(id),
        }
      })
    : [], // 如果 userIds 为 undefined,则返回空数组
})

注意useQueries 返回的是一个查询结果的数组

关于性能的一点说明

从定义上讲,依赖查询构成了一种请求瀑布(request waterfall),这会损害性能。假设两个查询耗时相同,串行执行所需的时间总是并行执行的两倍。这一点在高延迟的客户端上尤其明显。

如果可能,最好重构后端 API,使得这两个查询可以并行获取,但这并不总是可行的。例如,在上面的例子中,与其先调用 getUserByEmail 再调用 getProjectsByUser,不如引入一个新的 getProjectsByUserEmail 查询,从而消除请求的串行依赖。

最后更新于

这有帮助吗?