依赖(或串行)查询依赖于先前查询的完成才能执行。为此,使用 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,
})
// 获取用户
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'
status: 'pending'
isPending: true
fetchStatus: 'idle'
一旦 user 可用,projects 查询将被 enabled,然后将转换为:
status: 'pending'
isPending: true
fetchStatus: 'fetching'
status: 'pending'
isPending: true
fetchStatus: 'fetching'
一旦我们有了项目,它将变为:
status: 'success'
isPending: false
fetchStatus: 'idle'
status: 'success'
isPending: false
fetchStatus: 'idle'
动态并行查询 - 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 未定义,则将返回一个空数组
})
// 获取用户 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 未定义,则将返回一个空数组
})
注意 useQueries 返回一个查询结果数组
依赖查询本质上构成了一种请求瀑布流形式,这会损害性能。如果我们假设两个查询花费相同的时间,那么串行执行它们总是比并行执行花费两倍的时间,这在客户端延迟较高时尤其有害。如果可以,最好重构后端 API,以便可以并行获取这两个查询,尽管这在实践中可能并不总是可行。
在上面的示例中,与其先获取 getUserByEmail 以便能够 getProjectsByUser,不如引入一个新的 getProjectsByUserEmail 查询来展平瀑布流。