Start / Seminare / Next.js 16 Full-Stack-Entwicklung mit React und TypeScript

Modul

Navigation, Prefetching und UI-Zustände

6 Kapitel in diesem Modul-Video · Laufzeit

Vertonung mit synthetischer Stimme · Inhalte redaktionell verantwortet · © 2026 HECKER CONSULTING, alle Rechte vorbehalten

Transkript

Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.

Navigation, Prefetching und UI-Zustände

0:00 In diesem Modul geht es um etwas, das man nicht als Funktion auf einer Liste findet und trotzdem sofort bemerkt: wie sich eine Anwendung anfühlt. Was sieht jemand in der halben Sekunde, nachdem er geklickt hat? Was passiert, wenn eine Abfrage schiefgeht? Und warum wirken manche Seiten sofort da, während andere hängen? Next.js 16.3 hat gerade hier deutlich nachgelegt — unter dem Namen Instant Navigations steckt eine ganze Reihe von Werkzeugen.

0:26 Am Ende dieses Moduls können Sie eine langsame Navigation nicht nur beheben, sondern überhaupt erst finden. Und das ist der schwierigere Teil.

Navigieren mit Link und useRouter

0:35 Fangen wir beim Klick selbst an. Es gibt zwei Wege, in einer Next.js-Anwendung von einer Seite zur nächsten zu kommen, und sie unterscheiden sich in mehr als der Schreibweise. Einer von beiden ist der Normalfall, der andere die Ausnahme — und die Wahl hat Folgen dafür, ob Ihre Anwendung ohne JavaScript funktioniert und wie viel davon überhaupt in den Browser wandert.

0:56 Sehen wir uns beide an. Die Link-Komponente erzeugt einen ganz gewöhnlichen Anker — mit allem, was dazu gehört: Sie können ihn mit der mittleren Maustaste in einem neuen Tab öffnen, Sie können ihn kopieren, und er funktioniert auch dann, wenn kein JavaScript geladen ist. Zusätzlich übernimmt er das Vorabladen. Die zweite Variante ist ein Hook, mit dem Sie aus Code heraus navigieren — nach einer erfolgreichen Buchung etwa, wenn niemand geklickt hat.

1:22 Beides hat seine Berechtigung. Nur die Reihenfolge sollte stimmen: Erst der Anker, und der Hook nur, wenn es ohne ihn nicht geht. Das Bemerkenswerte an diesem Beispiel ist, was Sie nicht sehen. Es gibt keinen Klick-Handler, keinen Zustand, keinen Effekt. Die Komponente holt ihre Daten und gibt Anker aus — und weil sie das auf dem Server tut, landet für diese Liste kein einziges Byte JavaScript im Browser.

1:45 Der Nutzer bekommt trotzdem eine schnelle Navigation, weil Next.js die Ziele im Hintergrund vorlädt. Worauf es ankommt: Wenn Sie hier stattdessen einen Button mit einem Klick- Handler bauen würden, verlören Sie das Öffnen im neuen Tab, die Barrierefreiheit und den Betrieb ohne JavaScript — und gewännen nichts. Lesen Sie diese Tabelle spaltenweise, dann wird die Empfehlung offensichtlich.

2:08 Die linke Spalte kann fast alles, die rechte hat genau einen Vorteil: Sie funktioniert aus Code heraus. Dafür zahlen Sie mit einer Client-Komponente, also mit JavaScript im Browser. Das ist kein Verbot — nach einem Formularversand brauchen Sie diesen Weg. Aber es ist eine bewusste Entscheidung und keine Geschmacksfrage. Dasselbe gilt für die beiden verwandten Hooks, mit denen man den aktuellen Pfad oder die Suchparameter liest: Auch sie ziehen die Komponente in den Browser.

2:35 Wir kommen im nächsten Modul ausführlich auf diese Grenze zurück. Der letzte Punkt ist der, den ich am häufigsten in Reviews sehe. Eine Navigation in einem Effekt sieht harmlos aus und erzeugt Sprünge, die niemand ausgelöst hat — der Nutzer landet plötzlich woanders, weil eine Abhängigkeit sich geändert hat. Solche Fehler sind schwer zu reproduzieren und noch schwerer zu erklären.

2:57 Der mittlere Punkt ist eine Frage der Haltung: Ein Link, der als Button gebaut ist, nimmt Nutzern Möglichkeiten weg, die sie erwarten. Und der erste ist ein Vorgriff — jeder dieser Hooks verschiebt die Grenze zwischen Server und Browser ein Stück.

Ladezustände mit loading.tsx

3:11 Jetzt zu der halben Sekunde nach dem Klick. Was dort passiert, entscheidet darüber, ob eine Anwendung als schnell wahrgenommen wird — und zwar oft unabhängig davon, wie schnell sie tatsächlich ist. Next.js macht Ihnen den Ladezustand leicht, mit einer einzigen Datei. Und genau weil es so leicht ist, wird die Chance meistens vertan.

3:31 Sehen wir uns an, was hier gewonnen werden kann. Sie legen eine Datei neben die Seite, und Next.js zeigt deren Inhalt, solange geladen wird. Technisch spannt das Framework damit eine Suspense-Grenze um die Route und alles darunter — Sie schreiben also keine Bedingung und verwalten keinen Zustand. Das ist angenehm bequem. Wichtig zu verstehen: Diese Grenze umfasst die gesamte Route. Sie ist damit ein grobes Werkzeug.

3:56 Für den Anfang genau richtig, für den Feinschliff zu ungenau — und in einem Fall, den wir gleich sehen, greift sie sogar überhaupt nicht. Hier hilft ein Bild aus dem Alltag. Wenn Sie im Restaurant sitzen und der Kellner stellt schon einmal Teller und Besteck hin, wissen Sie: Das Essen kommt, und es wird ein Gedeck für zwei.

4:16 Ein rotierender Kreisel ist dagegen der Kellner, der Ihnen zuruft, es dauere noch. Beides ist eine Rückmeldung, aber nur eine davon sagt etwas. Der zweite Gewinn ist technisch: Ein Gerüst hat dieselbe Form wie der spätere Inhalt, deshalb springt die Seite beim Eintreffen der Daten nicht um. Und der dritte kommt in Kapitel fünf — genau dieses Gerüst ist es, was vorab geladen werden kann.

4:39 Sechs graue Zeilen statt eines Kreisels — mehr ist es nicht. Und trotzdem ist der Unterschied für den Nutzer erheblich, weil die Seite schon in der Wartezeit aussieht wie das, was gleich kommt. Achten Sie auf die Kennzeichnung im Markup: Ein Ladezustand sollte auch für jemanden erkennbar sein, der die Seite nicht sieht, sondern vorgelesen bekommt.

4:58 Worauf es ankommt: Bauen Sie das Gerüst aus denselben Bausteinen wie die echte Liste, sonst laufen die beiden im Laufe der Zeit auseinander, und beim Eintreffen der Daten ruckelt es doch. Und hier ist der Fall, in dem diese bequeme Datei nicht greift. Wenn ein Layout selbst ungecachte Daten liest, fällt es nicht auf den Ladezustand derselben Ebene zurück — es blockiert stattdessen die Navigation, bis es fertig ist.

5:22 Das ist unangenehm, weil es genau umgekehrt zur Erwartung ist: Sie haben einen Ladezustand definiert, und trotzdem hängt die Seite. Die gute Nachricht: Mit dem Caching-Modell, das wir in Modul sechs einschalten, meldet Next.js diesen Fall schon beim Bauen. Die praktische Konsequenz lautet trotzdem: Setzen Sie die Suspense-Grenze näher an den Datenzugriff.

Fehlerzustände und catchError

5:43 Kommen wir zu dem Fall, den niemand gern plant: Etwas geht schief. Die Frage ist nicht, ob das passiert, sondern was der Nutzer dann sieht — eine Sackgasse oder einen Weg zurück. Hier hat Next.js 16.3 etwas ergänzt, das ich für eine der nützlicheren Neuerungen halte, weil es aus einer Fehlermeldung eine echte Erholung macht. Sehen wir uns beide Ebenen an.

6:06 Die bekannte Variante fängt Fehler einer ganzen Route ab und bietet einen Neuversuch an. Neu seit 16.3 ist eine zweite Ebene: Fehlergrenzen um einzelne Teilbäume. Zwei Dinge machen sie besser als das, was es vorher gab. Erstens kommen sie den Framework-Funktionen für Nicht-gefunden und Weiterleitung nicht mehr in die Quere — ein Problem, das früher zu merkwürdigen Effekten führte.

6:28 Zweitens kann der Neuversuch tatsächlich Daten neu holen, statt nur den Browserzustand zurückzusetzen. Das ist der Unterschied zwischen einem Knopf, der etwas tut, und einem, der nur so aussieht. Das Muster ist schnell erzählt: Sie schreiben eine Ersatzdarstellung und geben sie in die Fehlergrenze hinein. Was dabei ankommt, sind der aufgetretene Fehler und eine Funktion für den erneuten Versuch.

6:52 Worauf es ankommt, ist der Umfang: Diese Grenze liegt nicht um die Seite, sondern um einen Teilbaum. Wenn also die Belegungsabfrage scheitert, bleibt der Rest des Dashboards stehen — die Kopfzeile, das Menü, die anderen Kacheln. Der Nutzer verliert eine Kachel und bekommt dort einen Knopf. Das ist etwas völlig anderes als eine leere Seite mit einer Entschuldigung.

7:14 Drei Ebenen, und die Regel darunter ist die eigentliche Botschaft: Je enger die Grenze, desto mehr Seite bleibt beim Fehler stehen. Denken Sie an Schotten in einem Schiff. Ein Leck in einer Kammer ist ein Problem, ein Leck ohne Schotten ist ein Untergang. Die oberste Zeile ist Ihr letztes Netz und sollte in keinem Projekt fehlen.

7:33 Die unterste ist die, mit der Sie tatsächlich arbeiten. Meine Empfehlung: Setzen Sie Fehlergrenzen dort, wo Sie externe Abhängigkeiten haben — fremde Dienste, Datenbanken, alles, was nicht Ihnen gehört. Es geht hier nicht um Höflichkeit gegenüber dem Nutzer, sondern um Verfügbarkeit. Eine Anwendung, in der ein fehlgeschlagener Aufruf die ganze Seite mitnimmt, ist genau so verfügbar wie ihr schwächster Dienst.

7:57 Mit engen Grenzen bleibt sie nutzbar, auch wenn ein Teil ausfällt. Der Neuversuch ohne vollständiges Neuladen kommt hinzu: Formulareingaben bleiben erhalten, die Scrollposition bleibt, der Nutzer verliert nichts. Meine Einschätzung: Das ist einer der Punkte, an denen sich eine sorgfältig gebaute Anwendung von einer schnell gebauten unterscheidet — und der Aufwand dafür ist überschaubar.

notFound, redirect, unauthorized und forbidden

8:19 Jetzt zu vier Antworten, die eine Anwendung geben kann, und zu der Frage, wann welche richtig ist. Das klingt nach Formalie, ist aber der Punkt, an dem sich später entscheidet, ob Sie Berechtigungsprobleme im Betrieb überhaupt bemerken. Zwei dieser vier sind vergleichsweise neu und werden noch selten genutzt — zu Unrecht, wie ich finde.

8:39 Die ersten beiden kennen Sie: Nicht gefunden bricht das Rendern ab und zeigt die passende Seite, die Weiterleitung schickt woandershin. Interessanter sind die beiden anderen, weil sie eine Unterscheidung möglich machen, die vorher im Code verschwand: nicht angemeldet gegenüber angemeldet, aber nicht berechtigt. Das sind zwei völlig verschiedene Lagen. Im ersten Fall soll sich jemand anmelden, im zweiten hilft ihm das nicht weiter.

9:02 Wer beides gleich beantwortet, schickt Nutzer in eine Schleife — sie melden sich an und landen wieder vor derselben Wand. Die Statuscodes rechts sind kein Selbstzweck. Sie sind das, was in Ihren Logs landet, und damit die Grundlage für jede spätere Auswertung. Wenn alles als Vierhundertvier durchgeht, sehen Sie nie, dass es ein Rechteproblem gibt — Sie sehen nur, dass Leute Seiten aufrufen, die es angeblich nicht gibt.

9:27 Machen Sie sich die Unterscheidung also von Anfang an zur Gewohnheit. Das kostet beim Schreiben eine Zeile und spart bei der ersten Störung eine Stunde. Das Hafenmeister-Beispiel unten macht es konkret: Ein Gast an der Rechnungsübersicht der Verwaltung bekommt Vierhundertdrei. Achten Sie auf die Reihenfolge, denn die ist nicht beliebig. Erst wird geklärt, wer da ist, dann was er darf, und erst danach, ob der Datensatz überhaupt existiert.

9:53 Dreht man das um, verrät die Anwendung Informationen: Wer eine Vierhundertvier bekommt, weiß, dass es den Datensatz nicht gibt — und wer stattdessen Vierhundertdrei bekommt, weiß, dass es ihn gibt. Diese Reihenfolge ist also eine Sicherheitsentscheidung, keine Stilfrage. Nebenbei bemerkt: Beide Antworten können richtig sein, je nachdem, ob die bloße Existenz eines Datensatzes schützenswert ist. Wir vertiefen das in Modul elf.

10:20 Der erste Punkt überrascht regelmäßig: Die Weiterleitung wirft intern eine Ausnahme, um den Ablauf abzubrechen. Code dahinter läuft nicht mehr — und wenn Sie den Aufruf in einen Block packen, der alle Ausnahmen abfängt, schlucken Sie genau diesen Mechanismus. Die Weiterleitung passiert dann nicht, und niemand sieht einen Fehler.

10:39 Der zweite und dritte Punkt sind zwei Seiten derselben Medaille: Wer alles als Nicht-gefunden beantwortet, verbirgt Rechteprobleme vor sich selbst. Wer immer Vierhundertdrei zeigt, verrät die Existenz. Welche Wahl richtig ist, hängt an den Daten.

Prefetching und Partial Prefetching

10:54 Kommen wir zu der Frage, warum manche Klicks sofort wirken. Der Trick ist alt: Man lädt die nächste Seite, bevor jemand darauf klickt. Interessant ist, wie viel man vorlädt — und genau da hat sich mit Version 16.3 grundlegend etwas geändert. Vorher gab es zwei grobe Einstellungen, jetzt gibt es eine feine. Sehen wir uns an, welches Problem damit verschwindet.

11:17 Bisher hatten Sie die Wahl zwischen zwei Extremen: entweder eine Ladehülle aus der Ladezustands-Datei, oder das aggressive Vorabladen der ganzen Zielseite. Beides hatte Nachteile. Die neue Variante geht dazwischen: Next.js zieht aus jeder Route die wiederverwendbare Hülle heraus, ganz gleich, ob Sie eine Ladezustands-Datei angelegt haben, und Sie steuern je Link, wie viel zusätzlich kommt.

11:39 Stellen Sie sich das vor wie einen Kellner, der schon einmal deckt, während die Bestellung noch läuft — er bringt nicht das ganze Menü, aber auch nicht nichts. Zwei Schalter in der Konfiguration, und das war es. Wichtig ist der Zusammenhang zwischen ihnen: Das Vorabladen setzt das neue Caching-Modell voraus, das wir uns in Modul sechs vornehmen.

11:59 Die beiden gehören zusammen, und das ist kein Zufall — was vorab geladen werden kann, hängt genau daran, was als cachebar markiert ist. Beide Verhaltensweisen sollen laut Hersteller in einer künftigen Hauptversion zum Standard werden. Wer heute ein neues Projekt beginnt, sollte sie also einschalten, statt später zu migrieren.

12:19 Der erste Punkt ist der wichtigste, weil er ein stilles Problem beschreibt: Eine vergessene Ladezustands-Datei machte eine Route unbemerkt langsam. Nichts ging kaputt, nichts wurde gemeldet — es fühlte sich nur zäh an, und niemand wusste warum. Dass die Hülle jetzt automatisch entsteht, nimmt diese Fehlerquelle heraus. Der zweite Punkt betrifft die Kosten: Aggressives Vorabladen kostet Serveraufrufe für Seiten, die niemand besucht.

12:45 Und die dritte Verbesserung ist unauffällig, aber messbar — kleine Nutzlasten werden gebündelt, aus vielen Anfragen werden wenige. Die Zeile in der Mitte ist die interessante. Wenn Sie an einem Link das Vorabladen ausdrücklich einschalten, wird die Zielseite mit ihrer konkreten Adresse vorgerendert — inklusive der Inhalte, die von Suchparametern oder Pfadangaben abhängen.

13:07 Der Nutzer klickt dann auf etwas, das serverseitig schon fertig ist. Das ist beeindruckend und kostet einen Serveraufruf je vorbereitetem Link. Die Empfehlung ergibt sich daraus von selbst: an wenigen, wahrscheinlich genutzten Links einschalten, nicht überall. In unserem Portal wäre das der Sprung von der Liegeplatzliste ins Detail.

Instant Navigations prüfen

13:26 Zum Abschluss des Moduls die vielleicht praktischste Neuerung: Werkzeuge, die Ihnen sagen, welche Navigation langsam ist. Das klingt banal, löst aber ein echtes Problem — man kann es nämlich lokal gar nicht sehen. Wer wissen will, warum, bekommt gleich die Antwort. Und wer denkt, das beträfe nur große Anwendungen, wird überrascht sein, wie leicht man sich so ein Problem einbaut.

13:50 Zwei Werkzeuge stecken dahinter. Das erste beobachtet Ihre Navigationen und meldet jene, die nicht sofort reagieren — samt einem Vorschlag, wie sich das beheben lässt. Das zweite hält den Ladevorgang an der Hülle an, so wie ein Standbild in einem Film. Sie sehen also genau das, was der Nutzer in dem Moment sieht, in dem er klickt.

14:09 Das ist deshalb so wertvoll, weil dieser Moment sonst zu kurz ist, um ihn zu beurteilen. Sie können nicht optimieren, was Sie nicht anschauen können. Der rote Faden dieser fünf Schritte ist eine Suche, die von außen nach innen geht. Sie beginnen mit dem, was das Werkzeug meldet, schauen sich dann an, was der Nutzer tatsächlich sieht, und suchen erst dann den blockierenden Zugriff.

14:32 Der sitzt fast immer an derselben Stelle: ein Warten auf Daten zu weit oben im Baum. Danach haben Sie drei Möglichkeiten, und alle drei sind legitim — cachen, in eine Suspense-Grenze fassen, oder den Zugriff nach unten verschieben. Welche richtig ist, hängt an den Daten. Wir arbeiten das in den Modulen fünf und sechs vollständig durch.

14:52 Und hier ist der Grund, warum man das lokal nicht sieht: Im Entwicklungsmodus ist das Vorabladen abgeschaltet. Sie arbeiten also den ganzen Tag in einer Umgebung, in der genau dieses Verhalten fehlt — und merken erst in Produktion, dass etwas zäh ist. Dort sucht dann niemand mehr danach, weil ja alles funktioniert. Der typische Auslöser ist übrigens harmlos: Jemand baut eine Komponente in den gemeinsamen Kopfbereich, die die Sitzung liest. Ab da ist jede Seite betroffen.

15:20 Das Werkzeug nennt Ihnen Route und Zeile. Diese Aufgabe ist bewusst als Suche angelegt, nicht als Reparatur. Sie sollen den blockierenden Zugriff finden und dann entscheiden, welche der drei Korrekturen hier passt — das ist die eigentliche Übung. Der Erfolg ist eindeutig ablesbar: Die Route taucht in der Meldung nicht mehr auf, und die Hülle zeigt Kopfzeile und Gerüst.

15:42 Ein Tipp aus der Praxis: Der übliche Auslöser ist ein Zugriff auf die Sitzung im Portal-Layout. Wenn Sie danach suchen, finden Sie es schneller — aber sehen Sie sich vorher an, was das Werkzeug meldet.

Modul 3 zusammengefasst

15:55 Halten wir fest: Der Anker ist der Normalfall, der Hook die Ausnahme. Ladezustände zeigen ein Gerüst, keine Kreisel. Fehlergrenzen gehören eng, damit beim Fehler möglichst viel stehen bleibt. Und die vier Antworten — nicht gefunden, nicht angemeldet, nicht berechtigt, verschoben — sind vier verschiedene Dinge. Im nächsten Modul kommen wir zu dem Thema, das ich schon mehrfach angekündigt habe: der Grenze zwischen Server und Browser.

16:21 Das ist der eigentliche Denkwechsel dieses Seminars, und alles, was danach kommt, baut darauf auf.

Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →