Framework
Version

Abhängige Queries

useQuery abhängige Abfrage

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.

js
// Get the user
const { data: user } = useQuery({
  queryKey: ['user', email],
  queryFn: () => getUserByEmail(email.value),
})

const userId = computed(() => user.value?.id)
const enabled = computed(() => !!user.value?.id)

// Then get the user's projects
const { isIdle, data: projects } = useQuery({
  queryKey: ['projects', userId],
  queryFn: () => getProjectsByUser(userId.value),
  enabled, // The query will not execute until `enabled == true`
})
// Get the user
const { data: user } = useQuery({
  queryKey: ['user', email],
  queryFn: () => getUserByEmail(email.value),
})

const userId = computed(() => user.value?.id)
const enabled = computed(() => !!user.value?.id)

// Then get the user's projects
const { isIdle, data: projects } = useQuery({
  queryKey: ['projects', userId],
  queryFn: () => getProjectsByUser(userId.value),
  enabled, // The query will not execute until `enabled == true`
})

Die Abfrage projects wird starten in

tsx
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

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

Sobald wir die Projekte haben, geht es weiter zu

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

useQueries abhängige Abfrage

Dynamische parallele Abfrage - useQueries kann auch von einer vorherigen Abfrage abhängen, hier erfahren Sie, wie Sie dies erreichen.

tsx
// Get the users ids
const { data: userIds } = useQuery({
  queryKey: ['users'],
  queryFn: getUsersData,
  select: (users) => users.map((user) => user.id),
})

const queries = computed(() => {
  return userIds.value.length
    ? userIds.value.map((id) => {
        return {
          queryKey: ['messages', id],
          queryFn: () => getMessagesByUsers(id),
        }
      })
    : []
})

// Then get the users messages
const usersMessages = useQueries({
  queries, // if userIds.value is undefined or has no items, 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),
})

const queries = computed(() => {
  return userIds.value.length
    ? userIds.value.map((id) => {
        return {
          queryKey: ['messages', id],
          queryFn: () => getMessagesByUsers(id),
        }
      })
    : []
})

// Then get the users messages
const usersMessages = useQueries({
  queries, // if userIds.value is undefined or has no items, an empty array will be returned
})

Beachten Sie, dass useQueries ein Array von Abfrageergebnissen zurückgibt.

Ein Hinweis zur Leistung

Abhängige Abfragen stellen per Definition eine Form eines Request Waterfalls dar, was die Leistung beeinträchtigt. Wenn wir annehmen, dass beide Abfragen gleich viel Zeit in Anspruch nehmen, dauert die serielle Ausführung anstelle der parallelen immer doppelt so lange, was besonders auf einem Client mit hoher Latenz schädlich ist. Wenn möglich, ist es immer besser, die Backend-APIs so umzustrukturieren, dass beide Abfragen parallel abgerufen werden können, auch wenn 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.