依赖(或串行)查询需要等待前一个查询完成才能执行。实现这一功能非常简单,只需使用 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),
}
})
: [], // 如果users未定义,则返回空数组
})
// 获取用户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),
}
})
: [], // 如果users未定义,则返回空数组
})
注意 useQueries 返回的是查询结果数组
依赖查询本质上构成了请求瀑布流,会影响性能。假设两个查询耗时相同,串行执行总是比并行执行多花一倍时间,这在客户端高延迟环境下尤其不利。如果可能,最好重构后端API使两个查询能并行获取,尽管这并非总是可行。
在上面的例子中,与其先获取getUserByEmail才能执行getProjectsByUser,不如新增一个getProjectsByUserEmail查询来消除瀑布流。