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 bilden per Definition eine Form von Anforderungs-Wasserfall, der die Leistung beeinträchtigt. Wenn wir davon ausgehen, dass beide Abfragen die gleiche Zeit in Anspruch nehmen, dauert die serielle Ausführung im Vergleich zur parallelen immer doppelt so lange, was besonders bei Latenzen auf dem Client schmerzhaft ist. Wenn möglich, ist es immer besser, die Backend-APIs so umzustrukturieren, dass beide Abfragen parallel abgerufen werden können, obwohl dies möglicherweise nicht immer praktisch umsetzbar 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.