Datenabfrage
Nachdem Sie Ihre Datenbank erstellt und mit Daten gefüllt haben, wollen wir die verschiedenen Möglichkeiten besprechen, wie Sie Daten für Ihre Anwendung abfragen können, und Ihre Dashboard-Übersichtsseite aufbauen.
Wahl der Datenabfragemethode
API-Schicht
APIs sind eine Vermittlungsschicht zwischen Ihrem Anwendungscode und der Datenbank. Es gibt einige Fälle, in denen Sie eine API verwenden könnten:
- Wenn Sie Dienste von Drittanbietern nutzen, die eine API bereitstellen.
- Wenn Sie Daten vom Client abfragen, sollten Sie eine API-Schicht haben, die auf dem Server läuft, um Ihre Datenbankgeheimnisse nicht dem Client preiszugeben.
In Next.js können Sie API-Endpunkte mit Route Handlers erstellen.
Datenbankabfragen
Wenn Sie eine Full-Stack-Anwendung erstellen, müssen Sie auch Logik schreiben, um mit Ihrer Datenbank zu interagieren. Für relationale Datenbanken wie Postgres können Sie dies mit SQL oder einem ORM tun.
Es gibt einige Fälle, in denen Sie Datenbankabfragen schreiben müssen:
- Beim Erstellen Ihrer API-Endpunkte müssen Sie Logik schreiben, um mit Ihrer Datenbank zu interagieren.
- Wenn Sie React Server Components verwenden (Datenabfrage auf dem Server), können Sie die API-Schicht überspringen und direkt Ihre Datenbank abfragen, ohne Risiko, Ihre Datenbankgeheimnisse dem Client preiszugeben.
Lassen Sie uns mehr über React Server Components erfahren.
Verwendung von Server Components für Datenabfragen
Standardmäßig verwenden Next.js-Anwendungen React Server Components. Die Datenabfrage mit Server Components ist ein relativ neuer Ansatz und bietet einige Vorteile:
- Server Components unterstützen JavaScript Promises und bieten eine native Lösung für asynchrone Aufgaben wie Datenabfragen. Sie können die
async/await
-Syntax verwenden, ohneuseEffect
,useState
oder andere Datenabfrage-Bibliotheken zu benötigen. - Server Components laufen auf dem Server, sodass Sie aufwändige Datenabfragen und Logik auf dem Server belassen können und nur das Ergebnis an den Client senden.
- Da Server Components auf dem Server laufen, können Sie direkt die Datenbank abfragen, ohne eine zusätzliche API-Schicht. Dies erspart Ihnen das Schreiben und Warten von zusätzlichem Code.
Verwendung von SQL
Für Ihre Dashboard-Anwendung werden Sie Datenbankabfragen mit der postgres.js-Bibliothek und SQL schreiben. Es gibt einige Gründe, warum wir SQL verwenden:
- SQL ist der Industriestandard für Abfragen relationaler Datenbanken (z.B. generieren ORMs SQL im Hintergrund).
- Ein grundlegendes Verständnis von SQL kann Ihnen helfen, die Grundlagen relationaler Datenbanken zu verstehen, sodass Sie Ihr Wissen auf andere Tools anwenden können.
- SQL ist vielseitig und ermöglicht es Ihnen, spezifische Daten abzufragen und zu manipulieren.
- Die
postgres.js
-Bibliothek bietet Schutz vor SQL-Injections.
Machen Sie sich keine Sorgen, wenn Sie SQL noch nicht verwendet haben – wir haben die Abfragen für Sie vorbereitet.
Gehen Sie zu /app/lib/data.ts
. Hier sehen Sie, dass wir postgres
verwenden. Die sql
-Funktion ermöglicht es Ihnen, Ihre Datenbank abzufragen:
Sie können sql
überall auf dem Server aufrufen, z.B. in einer Server Component. Aber um Ihnen die Navigation durch die Komponenten zu erleichtern, haben wir alle Datenabfragen in der data.ts
-Datei belassen, und Sie können sie in die Komponenten importieren.
Hinweis: Wenn Sie in Kapitel 6 Ihren eigenen Datenbankanbieter verwendet haben, müssen Sie die Datenbankabfragen an Ihren Anbieter anpassen. Sie finden die Abfragen in
/app/lib/data.ts
.
Datenabfrage für die Dashboard-Übersichtsseite
Nachdem Sie nun die verschiedenen Möglichkeiten der Datenabfrage verstanden haben, lassen Sie uns Daten für die Dashboard-Übersichtsseite abfragen. Navigieren Sie zu /app/dashboard/page.tsx
, fügen Sie den folgenden Code ein und nehmen Sie sich etwas Zeit, ihn zu erkunden:
Der obige Code ist absichtlich auskommentiert. Wir werden nun jedes Teil untersuchen.
- Die
page
ist eine asynchrone Server Component. Dies ermöglicht es Ihnen,await
für die Datenabfrage zu verwenden. - Es gibt auch 3 Komponenten, die Daten erhalten:
<Card>
,<RevenueChart>
und<LatestInvoices>
. Sie sind derzeit auskommentiert und noch nicht implementiert.
Datenabfrage für <RevenueChart/>
Um Daten für die <RevenueChart/>
-Komponente abzufragen, importieren Sie die fetchRevenue
-Funktion aus data.ts
und rufen Sie sie in Ihrer Komponente auf:
Als Nächstes führen Sie folgende Schritte aus:
- Heben Sie die Kommentierung der
<RevenueChart/>
-Komponente auf. - Navigieren Sie zur Komponentendatei (
/app/ui/dashboard/revenue-chart.tsx
) und heben Sie die Kommentierung des Codes darin auf. - Überprüfen Sie
localhost:3000
, und Sie sollten ein Diagramm sehen, das dierevenue
-Daten verwendet.

Lassen Sie uns fortfahren und weitere Daten importieren und im Dashboard anzeigen.
Datenabfrage für <LatestInvoices/>
Für die <LatestInvoices />
-Komponente müssen wir die letzten 5 Rechnungen abrufen, sortiert nach Datum.
Sie könnten alle Rechnungen abrufen und sie mit JavaScript sortieren. Dies ist bei unserer kleinen Datenmenge kein Problem, aber wenn Ihre Anwendung wächst, kann dies die übertragene Datenmenge und den benötigten JavaScript-Code für die Sortierung erheblich erhöhen.
Anstatt die letzten Rechnungen im Speicher zu sortieren, können Sie eine SQL-Abfrage verwenden, um nur die letzten 5 Rechnungen abzurufen. Zum Beispiel ist dies die SQL-Abfrage aus Ihrer data.ts
-Datei:
Importieren Sie in Ihrer Seite die fetchLatestInvoices
-Funktion:
Heben Sie dann die Kommentierung der <LatestInvoices />
-Komponente auf. Sie müssen auch den relevanten Code in der <LatestInvoices />
-Komponente selbst, die sich unter /app/ui/dashboard/latest-invoices
befindet, entkommentieren.
Wenn Sie Ihren localhost aufrufen, sollten Sie sehen, dass nur die letzten 5 Rechnungen aus der Datenbank zurückgegeben werden. Hoffentlich beginnen Sie zu erkennen, welche Vorteile die direkte Abfrage Ihrer Datenbank hat!

Übung: Daten für die <Card>
-Komponenten abfragen
Jetzt sind Sie an der Reihe, Daten für die <Card>
-Komponenten abzurufen. Die Karten zeigen folgende Daten an:
- Gesamtbetrag der bezahlten Rechnungen.
- Gesamtbetrag der ausstehenden Rechnungen.
- Gesamtzahl der Rechnungen.
- Gesamtzahl der Kunden.
Auch hier könnten Sie versucht sein, alle Rechnungen und Kunden abzurufen und die Daten mit JavaScript zu verarbeiten. Zum Beispiel könnten Sie Array.length
verwenden, um die Gesamtzahl der Rechnungen und Kunden zu erhalten:
Aber mit SQL können Sie nur die Daten abrufen, die Sie benötigen. Es ist etwas länger als die Verwendung von Array.length
, aber es bedeutet, dass weniger Daten während der Anfrage übertragen werden müssen. Hier ist die SQL-Alternative:
Die Funktion, die Sie importieren müssen, heißt fetchCardData
. Sie müssen die von der Funktion zurückgegebenen Werte destrukturieren.
Tipp:
- Überprüfen Sie die Card-Komponenten, um zu sehen, welche Daten sie benötigen.
- Überprüfen Sie die
data.ts
-Datei, um zu sehen, was die Funktion zurückgibt.
Wenn Sie bereit sind, erweitern Sie den folgenden Abschnitt für den endgültigen Code:
Großartig! Sie haben nun alle Daten für die Dashboard-Übersichtsseite abgerufen. Ihre Seite sollte nun so aussehen:

Allerdings... gibt es zwei Dinge, die Sie beachten sollten:
- Die Datenanfragen blockieren sich versehentlich gegenseitig und erzeugen einen Request-Wasserfall.
- Standardmäßig prerendert Next.js Routen, um die Leistung zu verbessern. Dies wird als Static Rendering bezeichnet. Wenn sich Ihre Daten ändern, wird dies nicht in Ihrem Dashboard widergespiegelt.
Lassen Sie uns Punkt 1 in diesem Kapitel besprechen und dann Punkt 2 im nächsten Kapitel genauer betrachten.
Was sind Request-Wasserfälle?
Ein "Wasserfall" bezieht sich auf eine Abfolge von Netzwerkanfragen, die von der Fertigstellung vorheriger Anfragen abhängen. Im Fall der Datenabfrage kann jede Anfrage erst beginnen, wenn die vorherige Anfrage Daten zurückgegeben hat.

Zum Beispiel müssen wir warten, bis fetchRevenue()
ausgeführt wurde, bevor fetchLatestInvoices()
starten kann, und so weiter.
Dieses Muster ist nicht unbedingt schlecht. Es kann Fälle geben, in denen Sie Wasserfälle wollen, weil eine Bedingung erfüllt sein muss, bevor Sie die nächste Anfrage stellen. Zum Beispiel möchten Sie möglicherweise zuerst die ID und Profilinformationen eines Benutzers abrufen. Sobald Sie die ID haben, können Sie dann die Liste seiner Freunde abrufen. In diesem Fall ist jede Anfrage von den Daten abhängig, die von der vorherigen Anfrage zurückgegeben wurden.
Dieses Verhalten kann jedoch auch unbeabsichtigt sein und die Leistung beeinträchtigen.
Parallele Datenabfrage
Eine gängige Methode, um Wasserfälle zu vermeiden, besteht darin, alle Datenanfragen gleichzeitig zu starten – parallel.
In JavaScript können Sie die Funktionen Promise.all()
oder Promise.allSettled()
verwenden, um alle Promises gleichzeitig zu starten. Zum Beispiel verwenden wir in data.ts
Promise.all()
in der fetchCardData()
-Funktion:
Mit diesem Muster können Sie:
- Alle Datenabfragen gleichzeitig starten, was schneller ist, als auf jede Anfrage in einem Wasserfall zu warten.
- Ein natives JavaScript-Muster verwenden, das auf jede Bibliothek oder jedes Framework angewendet werden kann.
Es gibt jedoch einen Nachteil, wenn Sie sich nur auf dieses JavaScript-Muster verlassen: Was passiert, wenn eine Datenanfrage langsamer ist als alle anderen? Lassen Sie uns das im nächsten Kapitel genauer untersuchen.