MobX vs. Redux

Beim Arbeiten mit beliebten Frameworks wie React oder Vue müssen wir eine bequeme Speicherung und Verwaltung des Anwendungszustands organisieren. Beispielsweise ermöglicht React die Verwaltung des Zustands von Komponenten direkt aus der Box mit this.setState und this.state. Doch mit dem Wachstum der Anwendung kommt der Bedarf an Kommunikation zwischen den Komponenten, was oft zu unzureichender Funktionalität führt. Zum Glück gibt es in der Frontend-Welt viele fertige Bibliotheken, die diese Aufgabe vereinfachen. Dieser Artikel behandelt zwei der derzeit beliebtesten Lösungen – Redux und MobX.

Über Redux und MobX

Derzeit ist die beliebteste Bibliothek zur Speicherung des Anwendungszustands Redux, die 2015 von Dan Abramov und Andrew Clark entwickelt wurde. Sie basiert auf der Flux-Architektur und funktionaler Programmierung. Redux-Benutzer profitieren von einer starken Community und einer umfangreichen Codebasis, sodass Fragen zur Bibliothek leicht beantwortet werden können.

Die am weitesten verbreitete Alternative ist MobX, die 2015 von Michel Weststrate entwickelt wurde. Sie basiert auf Prinzipien der funktionalen reaktiven Programmierung (FRP) und ermöglicht das Einwickeln von Zuständen in „observable“ Objekte. Dies erleichtert das Reagieren auf Änderungen im Anwendungszustand.

Datenfluss und wesentliche Unterschiede

Redux:

data flow Redux

  • Hat nur einen Store als einzige Quelle der Wahrheit. Der Zustand wird in einem regulären JavaScript-Objekt gespeichert. Es ist am besten, den Zustand normalisiert und flach zu halten.
  • Der Zustand ist unveränderlich. Jede Aktualisierung des Zustands gibt immer eine neue Kopie des Zustands zurück.
  • Alle Zustandsaktualisierungen werden durch das Dispatchen einer spezifischen Aktion durchgeführt.
  • Reducers reagieren auf Aktionen und geben eine neue Kopie des Zustands zurück, wenn dieser aktualisiert wurde.

MobX:

data flow MobX

  • Kann mehrere observable Stores haben. Die Struktur des Zustands ist denormalisiert und oft tief verschachtelt.
  • Der Zustand ist veränderlich. Er kann direkt geändert werden, aber es wird empfohlen, dies mit Aktionsfunktionen zu tun.
  • Wie die Dokumentation sagt: „MobX macht das State-Management wieder einfach, indem es das Grundproblem angeht: Es macht es unmöglich, einen inkonsistenten Zustand zu erzeugen.“
  • Alle Ableitungen werden automatisch und atomar aktualisiert, wenn sich der Zustand ändert.

Redux Store

Wie bereits erwähnt, speichert Redux Zustandsdaten in einem einzigen globalen Store, der die einzige Quelle der Wahrheit ist. Reducers, die ein Aktionsobjekt annehmen und eine aktualisierte Kopie des Zustands zurückgeben, werden zur Verwaltung verwendet. Das Aktionsobjekt ist ein einfaches JavaScript-Objekt, das das Aktionsfeld und die Nutzdatenfelder enthält. Reducers ermöglichen es, ein Zustandsobjekt in separate logische Einheiten zu unterteilen, wie z. B. artistReducer, articlesReducer, profileReducer, die später mit combineReducers zu einem Zustandsobjekt kombiniert werden. Der Store verfügt über die Methoden dispatch und subscribe, um den Zustand zu verwalten und auf Änderungen zu reagieren. Wenn nach dem Aufruf von dispatch der Zustand aktualisiert wird, werden alle Abonnenten benachrichtigt. Es wird jedoch viel Boilerplate-Code benötigt, um den Store zu beschreiben, was ein großer Nachteil für kleine Projekte ist. Ein Beispiel für einen Store in Redux:

MobX Store

Eine Anwendung, die MobX verwendet, hat tendenziell mehrere Stores, die den Zustand in logische Teile unterteilen, wie z. B. ein Domänenmodell oder UI-Zustand. Dies ermöglicht es, die Zustandsstruktur bequem zu organisieren und einzelne Stores in anderen Anwendungen wiederzuverwenden. MobX hat ein ziemlich hohes Abstraktionsniveau, das den Boilerplate-Code im Vergleich zu Redux erheblich reduziert. Dies ermöglicht es, Stores schnell mit @observable– und @computed-Anmerkungen oder den Funktionen makeObservable und makeAutoObservable zu erstellen. Änderungen am Zustand können entweder direkt vorgenommen werden, z. B. artistStore.artists.push(artist), oder, wie empfohlen, expliziter mit @action, wie im folgenden Beispiel gezeigt. Der einfachste Weg, auf Änderungen im Store zu reagieren, besteht darin, eine Reaktion zu erstellen, indem eine Rückruffunktion an die autorun-Funktion übergeben wird. Die Reaktion wird beim ersten Erstellen aufgerufen und immer dann, wenn observable und computed Werte im Store ändern. Der Hauptnachteil dieses Ansatzes ist, dass bei wachsenden Anwendungen komplexere und schwer zu debuggende Beziehungen zwischen Stores entstehen können. Das folgende Beispiel beschreibt einen MobX Store, der dem oben vorgestellten Redux Store ähnelt:

Beliebtheit & Kompatibilität

Gemessen an der starken Community-Unterstützung ist Redux zweifellos populärer als MobX. In dieser Bibliothek kann jeder Entwickler Lösungen für Redux-bezogene Probleme finden und ein praktisches Werkzeug zur Fehlerbehebung im Zustand von Redux DevTools verwenden. Dies vereinfacht den Prozess des Erlernens der Bibliothek. Die Notwendigkeit, eine große Menge an Boilerplate-Code zu schreiben, sowie viele Hilfsbibliotheken und Lösungen wie redux-saga, redux-thunk, reselect, normalizr, Middlewares usw., sind jedoch die Hauptursache für Kopfschmerzen auf dem Weg zur Beherrschung. In der Zwischenzeit bietet MobX eine hohe Abstraktion in den Anmerkungen, die einen schnellen Übergang vom Lernen zur Arbeit mit der Bibliothek ermöglicht.

MobX und Redux sind unabhängige Bibliotheken, die mit fast allen UI-Frameworks kompatibel sind. Für beliebte Lösungen wie React erleichtern fertige Pakete das Verbinden und Verwalten von Zuständen, wie z. B. mobx-react oder react-redux.

MobX Redux
Pros
  • Leicht zu erlernen
  • Wenig Boilerplate-Code
  • Volle TypeScript-Unterstützung
  • Große Community-Unterstützung
  • Einfaches Debugging und Testen
  • Flexibilität und Erweiterbarkeit dank reiner Reducer-Funktionen und Middlewares
Cons
  • Schwieriges Debugging
  • Hoher Grad an Freiheit bei der Datenhaltung, -strukturierung und -verarbeitung
  • Kompliziertes Skalieren, das mit dem Wachstum eines Projekts einhergeht
  • Viel Boilerplate-Code
  • Fehlende Seiteneffekte von Haus aus
  • Notwendigkeit, viele zusätzliche Bibliotheken zu erlernen
MobX
Pros
  • Leicht zu erlernen
  • Wenig Boilerplate-Code
  • Volle TypeScript-Unterstützung
Cons
  • Schwieriges Debugging
  • Hoher Grad an Freiheit bei der Datenhaltung, -strukturierung und -verarbeitung
  • Kompliziertes Skalieren, das mit dem Wachstum eines Projekts einhergeht
Redux
Pros
  • Große Community-Unterstützung
  • Einfaches Debugging und Testen
  • Flexibilität und Erweiterbarkeit dank reiner Reducer-Funktionen und Middlewares
Cons
  • Viel Boilerplate-Code
  • Fehlende Seiteneffekte von Haus aus
  • Notwendigkeit, viele zusätzliche Bibliotheken zu erlernen