Framework
Version

Queries

Query Basics

Eine Query ist eine deklarative Abhängigkeit von einer asynchronen Datenquelle, die an einen eindeutigen Schlüssel gebunden ist. Eine Query kann mit jeder Promise-basierten Methode (einschließlich GET- und POST-Methoden) verwendet werden, um Daten von einem Server abzurufen. Wenn Ihre Methode Daten auf dem Server modifiziert, empfehlen wir stattdessen die Verwendung von Mutations.

Um Ihre Queries in Ihren Komponenten oder benutzerdefinierten Hooks zu abonnieren, rufen Sie den useQuery Hook mit mindestens

  • Einem eindeutigen Schlüssel für die Query
  • Einer Funktion, die ein Promise zurückgibt, das
    • Die Daten auflöst oder
    • Einen Fehler auslöst
tsx
import { useQuery } from '@tanstack/react-query'

function App() {
  const info = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
}
import { useQuery } from '@tanstack/react-query'

function App() {
  const info = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
}

Der eindeutige Schlüssel, den Sie angeben, wird intern für das erneute Abrufen, Caching und Teilen Ihrer Queries in Ihrer gesamten Anwendung verwendet.

Das von useQuery zurückgegebene Query-Ergebnis enthält alle Informationen über die Query, die Sie für das Templating und jede andere Verwendung der Daten benötigen.

tsx
const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })

Das result-Objekt enthält einige sehr wichtige Zustände, die Sie kennen müssen, um produktiv zu sein. Eine Query kann zu jedem Zeitpunkt nur in einem der folgenden Zustände sein:

  • isPending oder status === 'pending' - Die Query hat noch keine Daten.
  • isError oder status === 'error' - Die Query ist auf einen Fehler gestoßen.
  • isSuccess oder status === 'success' - Die Query war erfolgreich und Daten sind verfügbar.

Zusätzlich zu diesen primären Zuständen stehen je nach Zustand der Query weitere Informationen zur Verfügung.

  • error - Wenn sich die Query im isError-Zustand befindet, ist der Fehler über die error-Eigenschaft verfügbar.
  • data - Wenn sich die Query im isSuccess-Zustand befindet, sind die Daten über die data-Eigenschaft verfügbar.
  • isFetching - In jedem Zustand, wenn die Query zu irgendeinem Zeitpunkt Daten abruft (einschließlich Hintergrundabfragen), ist isFetching true.

Für die meisten Queries ist es in der Regel ausreichend, den isPending-Zustand zu prüfen, dann den isError-Zustand und schließlich davon auszugehen, dass die Daten verfügbar sind, und den erfolgreichen Zustand zu rendern.

tsx
function Todos() {
  const { isPending, isError, data, error } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodoList,
  })

  if (isPending) {
    return <span>Loading...</span>
  }

  if (isError) {
    return <span>Error: {error.message}</span>
  }

  // We can assume by this point that `isSuccess === true`
  return (
    <ul>
      {data.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  )
}
function Todos() {
  const { isPending, isError, data, error } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodoList,
  })

  if (isPending) {
    return <span>Loading...</span>
  }

  if (isError) {
    return <span>Error: {error.message}</span>
  }

  // We can assume by this point that `isSuccess === true`
  return (
    <ul>
      {data.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  )
}

Wenn Booleans nicht Ihr Ding sind, können Sie auch den status-Zustand verwenden.

tsx
function Todos() {
  const { status, data, error } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodoList,
  })

  if (status === 'pending') {
    return <span>Loading...</span>
  }

  if (status === 'error') {
    return <span>Error: {error.message}</span>
  }

  // also status === 'success', but "else" logic works, too
  return (
    <ul>
      {data.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  )
}
function Todos() {
  const { status, data, error } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodoList,
  })

  if (status === 'pending') {
    return <span>Loading...</span>
  }

  if (status === 'error') {
    return <span>Error: {error.message}</span>
  }

  // also status === 'success', but "else" logic works, too
  return (
    <ul>
      {data.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  )
}

TypeScript wird auch den Typ von data korrekt einschränken, wenn Sie vor dem Zugriff darauf auf pending und error geprüft haben.

FetchStatus

Zusätzlich zum status-Feld erhalten Sie eine zusätzliche fetchStatus-Eigenschaft mit den folgenden Optionen:

  • fetchStatus === 'fetching' - Die Query ruft gerade Daten ab.
  • fetchStatus === 'paused' - Die Query wollte Daten abrufen, ist aber pausiert. Lesen Sie mehr dazu im Leitfaden Network Mode.
  • fetchStatus === 'idle' - Die Query tut im Moment nichts.

Warum zwei verschiedene Zustände?

Hintergrundaktualisierungen und Stale-While-Revalidate-Logik machen alle Kombinationen für status und fetchStatus möglich. Zum Beispiel:

  • Eine Query im success-Zustand hat normalerweise einen idle fetchStatus, könnte aber auch fetching sein, wenn eine Hintergrundaktualisierung stattfindet.
  • Eine Query, die gemountet wird und keine Daten hat, befindet sich normalerweise im pending-Zustand und im fetching fetchStatus, könnte aber auch paused sein, wenn keine Netzwerkverbindung besteht.

Denken Sie also daran, dass eine Query im pending-Zustand sein kann, ohne tatsächlich Daten abzurufen. Als Faustregel gilt:

  • Der status gibt Auskunft über die data: Haben wir welche oder nicht?
  • Der fetchStatus gibt Auskunft über die queryFn: Läuft sie oder nicht?

Weitere Lektüre

Für eine alternative Methode zur Überprüfung des Status werfen Sie einen Blick auf die Community Resources.