Abhängige (oder serielle) Abfragen hängen davon ab, dass frühere abgeschlossen sind, bevor sie ausgeführt werden können. Um dies zu erreichen, ist es so einfach wie die Verwendung der Option enabled, um einer Abfrage mitzuteilen, wann sie bereit zur Ausführung ist.
// Get the user
const { data: user } = useQuery(() => {
queryKey: ['user', email],
queryFn: getUserByEmail,
})
const userId = user?.id
// Then get the user's projects
const {
status,
fetchStatus,
data: projects,
} = useQuery(() => {
queryKey: ['projects', userId],
queryFn: getProjectsByUser,
// The query will not execute until the userId exists
enabled: !!userId,
})
// Get the user
const { data: user } = useQuery(() => {
queryKey: ['user', email],
queryFn: getUserByEmail,
})
const userId = user?.id
// Then get the user's projects
const {
status,
fetchStatus,
data: projects,
} = useQuery(() => {
queryKey: ['projects', userId],
queryFn: getProjectsByUser,
// The query will not execute until the userId exists
enabled: !!userId,
})
Die Abfrage projects wird starten in
status: 'pending'
isPending: true
fetchStatus: 'idle'
status: 'pending'
isPending: true
fetchStatus: 'idle'
Sobald der user verfügbar ist, wird die Abfrage projects enabled und wechselt dann zu
status: 'pending'
isPending: true
fetchStatus: 'fetching'
status: 'pending'
isPending: true
fetchStatus: 'fetching'
Sobald wir die Projekte haben, geht es weiter zu
status: 'success'
isPending: false
fetchStatus: 'idle'
status: 'success'
isPending: false
fetchStatus: 'idle'
Dynamische parallele Abfrage - useQueries kann auch von einer vorherigen Abfrage abhängen, hier erfahren Sie, wie Sie dies erreichen.
// Get the users ids
const { data: userIds } = useQuery(() => {
queryKey: ['users'],
queryFn: getUsersData,
select: (users) => users.map((user) => user.id),
})
// Then get the users messages
const usersMessages = useQueries(() => {
queries: userIds
? userIds.map((id) => {
return {
queryKey: ['messages', id],
queryFn: () => getMessagesByUsers(id),
}
})
: [], // if userIds is undefined, an empty array will be returned
})
// Get the users ids
const { data: userIds } = useQuery(() => {
queryKey: ['users'],
queryFn: getUsersData,
select: (users) => users.map((user) => user.id),
})
// Then get the users messages
const usersMessages = useQueries(() => {
queries: userIds
? userIds.map((id) => {
return {
queryKey: ['messages', id],
queryFn: () => getMessagesByUsers(id),
}
})
: [], // if userIds is undefined, an empty array will be returned
})
Beachten Sie, dass useQueries ein Array von Abfrageergebnissen zurückgibt.
Abhängige Abfragen stellen per Definition eine Form von Request Waterfall dar, was die Leistung beeinträchtigt. Wenn wir so tun, als ob beide Abfragen gleich lange dauern, dauert die serielle Ausführung anstelle der parallelen Ausführung immer doppelt so lange, was besonders auf einem Client mit hoher Latenz schmerzhaft ist. Wenn möglich, ist es immer besser, die Backend-APIs so umzustrukturieren, dass beide Abfragen parallel abgerufen werden können, auch wenn dies nicht immer praktisch durchführbar ist.
Im obigen Beispiel würde das Einführen einer neuen Abfrage getProjectsByUserEmail anstelle des ersten Abrufens von getUserByEmail, um getProjectsByUser abrufen zu können, den Wasserfall abflachen.