GraphQL-Clients mit React und Apollo, Teil 2
Seite 3: Caching von Daten
Der Apollo-Client legt die gelesenen Daten in einem Cache außerhalb der React UI-Komponenten ab, sodass sie bei einem erneuten Rendern der Komponente zur Verfügung stehen und nicht erneut geladen werden müssen. Der Cache ist dabei komponentenübergreifend gültig. Wenn die Anwendung an anderer Stelle dieselbe Query ausführt, liefert Apollo die Daten ebenfalls aus dem Cache. Selbst wenn die Daten (Felder) aus unterschiedlichen Queries an mehreren Stellen der UI dargestellt werden, aktualisiert die Applikation sie ebenfalls an allen Stellen und nicht nur in der Komponente, in der man gerade die Query ausgeführt hat. Dadurch ist sichergestellt, dass die Daten in der UI anwendungsweit konsistent sind.
Bis zu einem gewissen Grad lässt sich das Verhalten mit Redux vergleichen. Dort liegt der globale Anwendungszustand in einem zentralen Store außerhalb der Komponentenhierarchie. In Apollo liegen zumindest die vom Server geladenen Daten an zentraler Stelle außerhalb der UI-Komponenten, im Cache (es gibt sogar die Möglichkeit, auch clientseitigen Zustand in den Apollo Cache zu schreiben und daraus zu lesen und darauf über "lokale" GraphQL Queries zuzugreifen).
Der Inhalt des Caches sowie alle ausgeführten Queries lassen sich zur Laufzeit mit den Apollo Developer Tools inspizieren, einer Chrome-Erweiterung. In ihr ist ebenfalls der Explorer GraphiQL integriert, sodass man darüber auch direkt Queries, etwa zum Testen, absetzen kann.
Daten aktualisieren
Gelesene Daten sollen oftmals zu bestimmten Zeitpunkten eine Aktualisierung erhalten. Im Fall der Bierübersicht könnte es sinnvoll sein, die Liste der Biere jedes Mal erneut zu laden, wenn der Benutzer wieder auf die Übersichtsseite zurückkehrt, damit er stets die neusten Daten sieht. Dafür könnte man die fetch-Policy verändern, sodass die Daten nicht mehr aus dem Cache geliefert, sondern jedes Mal erneut vom Server gelesen werden. Sollen die Daten aktuell bleiben, wenn der Benutzer auf der Seite verweilt, gibt es die Möglichkeit, ein Poll-Intervall als Property zu übergeben. Die Query erfolgt dann periodisch im eingestellten Intervall.
Eine weitere Option wäre, Benutzern einen "Aktualisieren"-Knopf in der UI anzubieten, damit sie selbst bestimmen können, wann sie die dargestellten Daten erneut laden möchten. Um das zu ermöglichen, übergibt die Query-Komponente neben den oben gezeigten Informationen (loading, error, data) als weiteren Parameter eine refetch-Funktion an die Child-Komponente. Diese verwendet dann die übergeben Funktion, um zum Beispiel beim Drücken eines Knopfes die Daten erneut zu laden. Das folgende Listing illustriert das:
<Query query={OVERVIEW_PAGE_QUERY}>
{({ data, error, loading, refetch }) => {
if (error) { . . . }
if (loading) { . . . }
return (
<>
{data.beers.map(beer => (
<BeerImage . . . />
))}
<button onClick={refetch}>Aktualisieren</button>
</>
);
}}
</Query>