Start / Seminare / Angular Grundlagen & Moderne Patterns

Modul

State Management

5 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.

Angular — State Management

0:00 Zustand verwalten klingt nach einer technischen Detailfrage und ist in Wirklichkeit die Entscheidung, die eine Anwendung am stärksten prägt. Sie bestimmt, wie viel Code man lesen muss, um zu verstehen, warum auf dem Bildschirm gerade das steht, was dort steht. Angular hat hier in den letzten Jahren einen deutlichen Weg zurückgelegt — von RxJS als Standardantwort hin zu Signalen für den Normalfall.

0:21 In diesem Modul gehen wir diesen Weg nach: von den klassischen Stores über das schlichte Signal-Store-Muster bis zu NgRx, und wir klären, wann welcher Schritt gerechtfertigt ist.

Zustand verwalten in modernem Angular

0:31 Fünf Kapitel mit derselben Dramaturgie wie beim Architekturmodul: von einfach nach strukturiert, und jede Stufe muss sich rechtfertigen. Zuerst der Blick zurück auf die RxJS-Stores — nicht als Abrechnung, sondern um zu verstehen, was sie gut können und wo sie überdimensioniert sind. Dann das Signal-Store-Muster, das für die meisten Fälle die richtige Antwort ist.

0:52 Danach Seiteneffekte, NgRx SignalStore für die Fälle, in denen mehr Struktur gebraucht wird, und zum Schluss die Fassade — ein kleiner Kniff, der eine spätere Entscheidung offenhält. Kurz zu Ihnen, bevor wir loslegen. Diese drei Fragen entscheiden darüber, worauf wir den Schwerpunkt legen. Wer heute NgRx im Einsatz hat, hört dieses Modul anders als jemand, der mit einem halben Dutzend Services arbeitet.

1:16 Die zweite Frage ist die aufschlussreichste: Woran hakt es konkret? Zu viel Boilerplate ist ein anderes Problem als Code, den neue Kolleginnen und Kollegen nicht verstehen — und beides ist wieder etwas anderes als eine Oberfläche, die sich nicht aktualisiert. Und die dritte: Was soll am Ende entschieden sein?

Klassische RxJS-basierte Stores

1:35 Fangen wir dort an, wo die meisten Projekte stehen. RxJS war jahrelang die vorgesehene Antwort auf die Frage nach Zustand, und es gibt viel Code, der genau so aussieht. Schauen wir uns an, was daran gut ist und wo die Reibung entsteht. Und ich möchte das ausdrücklich nicht als Abrechnung erzählen: RxJS ist ein hervorragendes Werkzeug.

1:55 Die Frage ist nur, ob es für jede Aufgabe das richtige ist. Das Muster ist etabliert: ein Service kapselt ein Subject, gibt ein Observable nach außen und baut mit Operatoren die Kette, die Nachladen und Umformen regelt. Wer RxJS beherrscht, liest das flüssig. Wer es nicht beherrscht, sieht erst einmal eine Wand. Und genau das ist der springende Punkt — nicht, ob das Muster korrekt ist, sondern wie viel Vorwissen es voraussetzt für eine Aufgabe, die im Kern lautet: Hol mir eine Liste von Teilen und merke sie dir.

2:26 Schauen Sie hier nicht auf die einzelnen Zeilen, sondern auf das Verhältnis. Der Zweck dieses Service passt in einen Satz: Teile laden, bereitstellen, auf Wunsch neu laden. Um das zu lesen, brauchen Sie aber Subjects, Pipes, switchMap und shareReplay — vier Konzepte, von denen keines mit Fahrradteilen zu tun hat. Das ist keine schlechte Programmierung, es ist ein mächtiges Werkzeug für eine einfache Aufgabe.

2:50 Wie ein Kran, um einen Blumentopf umzustellen: Er schafft das zuverlässig, und trotzdem fragt man sich, ob es nötig war. Die ersten beiden Punkte sind die, die im Alltag Zeit kosten. Jeder Konsument muss abonnieren und das Abo wieder beenden — vergisst man das, leckt Speicher, und zwar leise. Der zweite Punkt ist der, der in modernen Anwendungen dazukommt: Ohne Zone.js löst ein neuer Wert allein kein Rendern mehr aus.

3:16 Die Oberfläche bleibt einfach stehen, ohne Fehlermeldung. Der dritte ist der bekannte async-Pipe, den man im Template vergisst. Und der vierte ist der grundsätzliche: Der eigentliche Zweck des Service verschwindet hinter der Operator-Kette. Und jetzt die Gegenrede, denn sie ist genauso wichtig. Überall dort, wo die Abfolge über die Zeit selbst die Fachlichkeit ist, ist RxJS unverändert die richtige Wahl und den Signalen deutlich überlegen.

3:43 Eine Suchfeld-Eingabe, die entprellt und dann eine Anfrage auslöst, deren Vorgängerin abgebrochen wird — versuchen Sie das mit Signalen, und Sie schreiben RxJS nach. Dasselbe gilt für WebSockets, für das Zusammenführen mehrerer Quellen, für alles, was mit Reihenfolge und Timing zu tun hat. Die Frage ist nie „Signals oder RxJS", sondern: Ist mein Zustand ein Wert oder ein Verlauf?

Das Signal-Store-Muster

4:07 Kommen wir zu dem, was ich für die meisten Anwendungen als Ausgangspunkt empfehle. Und die gute Nachricht vorweg: Sie brauchen dafür keine Bibliothek und kein neues Vokabular. Das Muster besteht aus Dingen, die Sie längst kennen — nur anders zusammengesetzt. Der Aufwand ist geringer, als der Begriff „Store" vermuten lässt — und für die allermeisten Anwendungen reicht genau das aus.

4:29 Ein Signal Store ist ein gewöhnlicher Angular-Service. Das ist wirklich alles. Er hält seinen Zustand privat und gibt nach außen abgeleitete Signale und Methoden. Wenn Ihnen das bekannt vorkommt — ja, das ist Kapselung, wie man sie seit Jahrzehnten lernt. Neu ist nur, dass die nach außen gegebenen Werte Signale sind und deshalb von selbst dafür sorgen, dass die Oberfläche stimmt.

4:52 Der Begriff „Store" ist dabei fast zu groß für die Sache. Es ist ein Service mit Disziplin darüber, was er hergibt und was nicht. Der erste Punkt beschreibt den Unterschied im Alltag am besten: Konsumenten lesen Werte. Kein Abonnieren, kein Aufräumen, kein Nachdenken über Lebenszyklen. Der zweite ist der, der in zoneless Anwendungen den Ausschlag gibt — es funktioniert einfach, ohne dass jemand die Change Detection anstoßen muss.

5:19 Der dritte ist eine Entwurfstugend: Was privat ist, kann von außen niemand verstellen. Und der vierte ist der, den man erst bei der Einarbeitung neuer Kolleginnen und Kollegen schätzt: kein zusätzliches Paket, keine neue Begriffswelt, die man erst lernen muss. Achten Sie auf die Trennlinie in diesem Code. Oben, privat: die Ressource, die die Daten holt.

5:41 Darunter, öffentlich: drei abgeleitete Signale — die Teile selbst, ein Ladezustand und ein Fehlerzustand. Das ist die ganze Idee. Die Ressource bleibt drinnen, weil sie ein technisches Detail ist. Was herauskommt, sind Werte, mit denen ein Template etwas anfangen kann. Und dazu eine Methode zum Nachladen. Vergleichen Sie das gedanklich mit dem RxJS-Service von vorhin: Derselbe Zweck, aber die Konsumenten müssen nichts mehr wissen.

6:09 Der zweite Anwendungsfall ist der interessantere, weil hier keine Schnittstelle im Spiel ist. Der Warenkorb entsteht in der Anwendung selbst. Das Muster bleibt gleich: ein privates, schreibbares Signal innen, ein nur-lesbares und ein abgeleitetes außen. Wichtig ist die Methode am Ende — sie erzeugt eine neue Liste, statt die bestehende zu verändern.

6:31 Das ist kein Stilpunkt, sondern Voraussetzung dafür, dass die Änderung überhaupt bemerkt wird. Ein mutiertes Array bleibt dasselbe Array, und für ein Signal heißt das: nichts passiert. Diese Aufgabe übt weniger die Syntax als eine Denkweise: Zustand als Wert zu modellieren statt als Ereignisstrom. Geschafft haben Sie es, wenn der Service nur noch Signale hergibt und kein Konsument mehr abonniert oder aufräumt.

6:55 Die Kür ist eine gute Kontrollfrage: Suchen Sie im Template nach einem übrig gebliebenen async-Pipe. Findet sich einer, ist die Umstellung noch nicht durch — und meistens sitzt genau dort die Stelle, an der man beim Umbauen unsicher war. Der erste Punkt ist der Entwurfsfehler, der am häufigsten passiert: Das schreibbare Signal wird öffentlich, und damit kann jede Komponente den Zustand umschreiben.

7:19 Damit ist die Kapselung dahin, und Fehlersuche wird zur Detektivarbeit. Der zweite Punkt ist die verpasste Gelegenheit — ableitbare Werte als eigenes Signal zu speichern heißt, sie synchron halten zu müssen. Der dritte ist die Mutation, die wir gerade besprochen haben. Und der vierte ist die Übertreibung in die andere Richtung: aus einem Service, der reicht, eine Bibliotheksarchitektur zu bauen.

Seiteneffekte mit effect

7:42 Ein kurzes, aber wichtiges Kapitel. Bisher ging es darum, Zustand zu halten und abzuleiten. Jetzt geht es um die Frage, was passieren soll, wenn sich etwas ändert — und zwar außerhalb der Oberfläche. Speichern, protokollieren, melden. Dafür gibt es einen eigenen Baustein, und er wird gern missverstanden. Denn effect ist der Baustein, den man am schnellsten falsch einsetzt: Er sieht aus, als wäre er für alles zuständig, was auf Änderungen reagiert.

8:11 Die Funktion effect führt ihren Inhalt erneut aus, sobald eines der darin gelesenen Signale sich ändert. Das Bemerkenswerte ist, wie die Abhängigkeit zustande kommt: Sie melden nichts an. Es genügt, dass Sie das Signal lesen. Man kann sich das vorstellen wie einen Zettel, auf dem steht, was man gelesen hat — und wer immer eines dieser Dinge ändert, muss Bescheid geben.

8:32 Angenehm ist auch, was Sie nicht tun müssen: Um das Aufräumen kümmert sich Angular, wenn die Komponente oder der Service verschwindet. Ein Beispiel, das im Alltag ständig gebraucht wird: Der Warenkorb soll einen Seitenwechsel überstehen. Worauf es hier ankommt, steht in der ersten Zeile innerhalb der Funktion. Dass die Positionen gelesen werden, ist das, was die Verbindung herstellt — und nicht etwa eine Angabe, welches Signal beobachtet werden soll.

8:59 Diese Automatik ist bequem und hat eine Kehrseite, über die wir gleich sprechen: Sie funktioniert nur für Signale, die tatsächlich gelesen werden. Was in einem nicht durchlaufenen if-Zweig steht, zählt nicht. Der erste Punkt nennt die typischen Fälle: Persistenz, Protokollierung, Meldung an ein Analysewerkzeug. Alles Dinge, die man früher an Subscriptions gehängt hat, mit dem entsprechenden Verwaltungsaufwand.

9:23 Der zweite und dritte Punkt sind die Bequemlichkeit — Abhängigkeiten ergeben sich, Aufräumen erledigt das Framework. Und der vierte ist der, der es in modernen Anwendungen zum Standardwerkzeug macht: Es passt bruchlos in eine Anwendung ohne Zone.js, weil es auf derselben Mechanik beruht wie alles andere dort. Der erste Punkt ist der wichtigste dieser Folie und der häufigste Fehler überhaupt: effect für Ableitungen zu nutzen.

9:49 Wenn Sie einen Wert aus anderen Werten berechnen, ist computed das richtige Werkzeug — effect ist für das gedacht, was nach außen wirkt. Der zweite Punkt ist die Endlosschleife, die entsteht, wenn ein Effekt sein eigenes Signal setzt. Der dritte ist die Kehrseite der Automatik, die wir eben besprochen haben. Und der vierte betrifft die Performance: Was bei jeder Änderung läuft, sollte nicht teuer sein.

NgRx SignalStore

10:12 Jetzt die nächste Stufe — und wieder gilt: Sie muss verdient sein. NgRx bringt Struktur und Erweiterbarkeit mit, und beides ist wertvoll, sobald man viele Stores und mehrere Teams hat. Bei drei Services in einer Anwendung ist es Ballast. Schauen wir uns an, was es tatsächlich bietet. Die Faustregel bleibt dieselbe wie beim Architekturmodul: Mehr Struktur muss durch einen benennbaren Schmerz bezahlt sein, sonst zahlt man nur den Preis.

10:39 Der SignalStore setzt einen Store aus benannten Bausteinen zusammen: einer für den Zustand, einer für die Ableitungen, einer für die Methoden. Das ist im Ergebnis dasselbe, was Sie vorhin von Hand geschrieben haben — nur dass die Form vorgegeben ist. Und genau darin liegt der Wert. Wenn zwanzig Stores in fünf Teams alle dieselbe Gliederung haben, findet man sich in jedem sofort zurecht.

11:01 Es ist wie bei den Konventionen aus dem Style Guide: Der Nutzen liegt nicht in der einzelnen Regel, sondern darin, dass alle dieselbe nehmen. Der erste Punkt ist der eigentliche Grund: einheitliche Struktur über viele Stores hinweg. Der zweite ist der, der im Alltag am meisten Freude macht — die Erweiterbarkeit. Es gibt ein Ökosystem von Zusatzbausteinen, und ein Store lässt sich um Funktionen ergänzen, die man sonst selbst schreiben müsste.

11:28 Wir sehen gleich ein Beispiel, das aus einer einzigen Zeile besteht. Der dritte Punkt ist technisch: Teilzustände lassen sich gezielt aktualisieren. Und der vierte macht die Integration bequem — der Store kann sich direkt als injizierbarer Service bereitstellen. Lesen Sie das nicht als Syntax, sondern als Gliederung. Erst der Zustand mit seinen Anfangswerten, dann die Ableitungen, dann die Methoden.

11:52 Drei Abschnitte, immer in dieser Reihenfolge, in jedem Store. Was am Ende dabei herauskommt, ist wieder ein Objekt mit Signalen darauf — für die Konsumenten fühlt es sich also an wie der handgeschriebene Service von vorhin. Die eine neue Sache, die Sie kennen sollten, steht in der Methode: patchState aktualisiert gezielt einen Teil des Zustands, statt alles neu zu setzen.

12:14 Fünf Schritte, die nach Rezept klingen und es auch sind. Interessant sind zwei Details. Beim zweiten Schritt legen Sie mit dem Anfangszustand zugleich den Typ fest — das ist der Moment, in dem Sie entscheiden, was dieser Store überhaupt weiß. Nehmen Sie sich dafür Zeit, das hält länger als alles andere. Und der fünfte Schritt ist die angenehme Überraschung: Der Store wird ganz normal injiziert.

12:36 Für die Konsumenten sieht er aus wie jeder andere Service — was gleich noch wichtig wird. Das ist die Zeile, für die sich der ganze Abschnitt lohnt. Vorhin haben wir die Persistenz des Warenkorbs von Hand mit einem Effekt gebaut — fünf Zeilen, plus das Zurücklesen beim Start, plus die Fehlerbehandlung, wenn im Speicher etwas Unerwartetes steht.

12:56 Hier ist es ein Baustein mit einem Schlüssel. Das ist der Ertrag der Erweiterbarkeit, und es gibt eine ganze Reihe solcher Bausteine aus der Community. Man sollte das nicht überbewerten — aber wenn ein Team zwanzig Stores pflegt, summieren sich solche Zeilen zu echter Zeit. Der erste Punkt ist der wichtigste im ganzen Kapitel, und er wiederholt die Grundregel dieses Moduls.

13:18 NgRx zu wählen, weil es mächtig wirkt, ist derselbe Fehler wie Micro-Frontends für ein Ein-Personen-Team. Der zweite Punkt ist der praktische Stolperstein beim Ausprobieren: Nach einem Branch-Wechsel fehlen die Pakete, und die Fehlermeldung führt einen erst in die Irre. Der dritte betrifft die Mechanik: Zustand wird über patchState geschrieben, nicht direkt verändert. Und der vierte leitet über zum letzten Kapitel.

Die Fassade vor dem Store

13:43 Ein kurzes Kapitel mit einem großen Effekt. Es geht um eine Eigenschaft, die man erst bemerkt, wenn es zu spät ist: Eine Store-Bibliothek breitet sich in der Anwendung aus, ohne dass es jemand beschließt. Und es gibt einen einfachen Weg, das zu verhindern. Es kostet ein paar Zeilen und hält Ihnen eine Tür offen, die sonst nach ein paar Monaten zugefallen ist.

14:04 Eine Fassade ist ein schmaler Service, der den Store intern benutzt und nach außen nur fachliche Signale und Methoden zeigt. Man kann sich das vorstellen wie den Tresen in einer Werkstatt: Der Kunde sagt, was er möchte, und sieht nicht, mit welchen Werkzeugen dahinter gearbeitet wird. Das ist kein Selbstzweck. Es geht darum, dass die Entscheidung für eine bestimmte Bibliothek an einer Stelle bleibt, statt in fünfzig Komponenten einzusickern — denn genau das macht sie später unumkehrbar.

14:31 Der erste Punkt macht das Problem greifbar. Ohne Fassade taucht ein NgRx-eigener Typ im abgeleiteten Typ jedes Konsumenten auf. Das ist kein Fehler und stört zunächst niemanden — es bedeutet nur, dass jede dieser Komponenten formal von NgRx abhängt. Der zweite Punkt ist die Konsequenz: Ein späterer Wechsel bleibt eine lokale Änderung statt eines Großprojekts.

14:53 Der dritte ist ein Nebeneffekt, den ich schätze — die öffentliche Schnittstelle spricht plötzlich Fachsprache. Und der vierte macht Tests deutlich einfacher. Der entscheidende Satz steht nicht im Code, sondern in der Fußzeile: Der Store wird nicht mehr exportiert. Genau das ist der Punkt. Eine Fassade, neben der der Store weiterhin öffentlich ist, kapselt nichts — sie ist dann nur eine zusätzliche Datei.

15:17 Ansonsten sehen Sie hier vor allem Durchreichen: Signale werden weitergegeben, Methoden weitergeleitet. Das wirkt zunächst nach unnötiger Schreibarbeit. Es ist aber die Stelle, an der Sie später etwas ändern können, ohne die halbe Anwendung anzufassen. Diese Aufgabe hat eine besonders schöne Erfolgskontrolle. Bauen Sie die Fassade ein und fahren Sie dann im Editor über die injizierte Eigenschaft in einer Komponente.

15:42 Wenn dort nur noch Ihr eigener Service steht und nichts, was nach Store-Bibliothek klingt, hat es funktioniert. Das dauert zehn Sekunden und ist aussagekräftiger als jedes Durchlesen. Und es zeigt zugleich, wie unauffällig die Verbreitung solcher Typen vorher war — man sieht sie nämlich nur, wenn man gezielt hinschaut. Die ersten beiden Punkte beschreiben halbe Fassaden, und die sind schlimmer als gar keine, weil sie ein Sicherheitsgefühl erzeugen.

16:08 Wer den Store weiter exportiert oder Store-Typen durchreicht, hat eine zusätzliche Datei und keinen Gewinn. Der dritte ist der schleichende: Fassaden neigen dazu, Logik anzuziehen, bis sie selbst ein zweiter Store sind. Und der vierte ist die notwendige Relativierung — beim schlichten Signal Store aus dem zweiten Kapitel brauchen Sie das alles nicht. Dort ist der Service bereits die Fassade.

16:30 Vier Fragen, die Sie sich in dieser Reihenfolge stellen sollten. Reicht ein Service mit signal und computed? Dann bleiben Sie dabei — das ist keine Verlegenheitslösung, sondern für die meisten Anwendungen die richtige Antwort. Brauchen Sie Struktur über viele Stores hinweg, prüfen Sie NgRx. Setzen Sie NgRx ein, ziehen Sie grundsätzlich eine Fassade davor, es kostet fast nichts.

16:54 Und wenn Ihr Zustand ein echter Verlauf über die Zeit ist — dann bleibt RxJS die richtige Wahl, und keine der drei anderen Antworten wird daran etwas ändern.

Fragen & Weiterarbeiten

17:04 Im nächsten Modul wechseln wir von der Frage, wie Zustand verwaltet wird, zu der Frage, was das kostet: Performance. Es geht um die Werkzeuge, mit denen man Ladezeit und Laufzeit tatsächlich misst, statt sie zu vermuten — und um zwei Stellschrauben, die im Alltag am meisten bringen. Interessanterweise hängt das eng mit diesem Modul zusammen: Wer Signale nutzt, kann sich eine Change-Detection-Strategie leisten, die früher heikel war.

17:29 Für die Nachlese sind die Dokumentation zum NgRx SignalStore und das zugehörige Toolkit die richtigen Anlaufstellen.

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