Redux & RxJS, Ähnlichkeiten?

113

Ich weiß, dass Redux eine bessere "Implementierung" von Flux ist, oder besser gesagt, es ist ein Redesign zur Vereinfachung (Verwaltung des Anwendungsstatus).

Ich habe viel über reaktives Programmieren (RxJS) gehört, aber ich habe noch nicht getaucht, um es zu lernen.

Meine Frage lautet also: Gibt es einen Schnittpunkt (etwas gemeinsam) zwischen diesen beiden Technologien oder ergänzen sie sich? ... oder ganz anders?

Oswaldo
quelle

Antworten:

185

Kurz gesagt, es handelt sich um sehr unterschiedliche Bibliotheken für sehr unterschiedliche Zwecke, aber ja, es gibt einige vage Ähnlichkeiten.

Redux ist ein Tool zum Verwalten des Status in der gesamten Anwendung. Es wird normalerweise als Architektur für Benutzeroberflächen verwendet. Betrachten Sie es als Alternative zu (der Hälfte von) Angular.

RxJS ist eine reaktive Programmierbibliothek. Es wird normalerweise als Tool zum Ausführen asynchroner Aufgaben in JavaScript verwendet. Betrachten Sie es als Alternative zu Versprechen.


Reaktive Programmierung ist ein Paradigma (Arbeitsweise und Denken), bei dem Datenänderungen aus der Ferne beobachtet werden . Daten werden aus der Ferne nicht geändert .

Hier ist ein Beispiel für aus der Ferne geändert :

// In the controller.js file
model.set('name', 'George');

Das Modell wird vom Controller aus geändert .

Hier ist ein Beispiel aus der Ferne beobachtet :

// logger.js
store.subscribe(function (data) {
    console.log(data);
});

Im Logger beobachten wir die Datenänderungen, die im Store (aus der Ferne) auftreten, und schreiben in die Konsole.


Redux verwendet das reaktive Paradigma nur ein wenig: Der Store ist reaktiv. Sie legen den Inhalt nicht aus der Ferne fest. Deshalb gibt es store.set()in Redux keine . Der Store beobachtet Aktionen aus der Ferne und ändert sich selbst. Und der Store ermöglicht es anderen, seine Daten aus der Ferne zu beobachten.

RxJS verwendet auch das reaktive Paradigma, aber anstatt eine Architektur zu sein, bietet es Ihnen grundlegende Bausteine, Observables , um dieses Muster "Beobachten aus der Ferne" zu erreichen.

Abschließend sehr unterschiedliche Dinge für unterschiedliche Zwecke, aber einige Ideen teilen.

André Staltz
quelle
4
Nein, du solltest sie nicht zusammen verwenden. Die Leute haben Redux mit Rx emuliert. Ein schnelles Google findet Beispiele für Sie. Wenn Sie Rx für Ihre reaktive Benutzeroberfläche verwenden möchten, lesen Sie Cycle.js, Andres Framework. Ich habe es in letzter Zeit benutzt und es ist fantastisch. Die API hat sich in letzter Zeit stark verändert, aber ich glaube, er fängt endlich an, Teile davon einzufrieren.
Joel Dentici
17
Laut den offiziellen Redux-Dokumenten "arbeiten sie hervorragend zusammen."
Galki
12
Sie arbeiten großartig zusammen! Es gibt eine Redux-Middleware, mit der Sie RxJS und Observables für Redux-Aktionen verwenden können. github.com/redux-observable/redux-observable Zusätzlich schrieb ich einen Blog-Beitrag über das How To: robinwieruch.de/redux-observable-rxjs
Robin Wieruch
1
Das Redux-Paradigma hat dazu beigetragen, dass meine Codebasis für Android-Projekte reaktiver wurde. Unsere Datenflüsse, die von Schaltflächen und anderen Feldern kommen, um einen Status in Verbindung mit RxJava zu aktualisieren, haben unsere Lesbarkeit und Leistung verbessert. Die Bibliotheken passen definitiv gut zusammen und ihre Vorteile sind sprachunabhängig.
Kenny Worden
Sie arbeiten hervorragend zusammen, aber in der Praxis kann Reactive für Sie tun, was Redux tun würde - den Status Ihrer Komponenten mit dem Modell synchronisieren, so oft macht es wenig Sinn, beide zu verwenden
Filip Sobczak
32

Das sind sehr unterschiedliche Dinge.

RxJS kann für die reaktive Programmierung verwendet werden und ist eine sehr gründliche Bibliothek mit mehr als 250 Operatoren.

Und Redux ist wie im Github-Repo beschrieben "Redux ist ein vorhersehbarer Statuscontainer für JavaScript-Apps".

Redux ist nur ein Tool zum Behandeln des Status in Apps. Im Vergleich dazu könnten Sie eine vollständige App in nur RxJS erstellen.

Hoffe das hilft :)

cmdv
quelle
3
Ihre Antwort ist auch gut @cmdv. Ich habe es nicht gesehen, als ich meins schrieb.
André Staltz
4

Redux ist nur eine Zustandsverwaltungsbibliothek mit genau definierten Standards für Aktualisierungsvorgänge. Wenn Sie sich an die Standards halten, können Sie Ihren Datenfluss vernünftig und leicht zu begründen halten. Es bietet auch die Möglichkeit, den Datenfluss mit Middleware und Store Enhancern zu verbessern.

RxJS ist ein Toolkit für die reaktive Programmierung. Sie können sich tatsächlich alles, was in Ihrer App passiert, als Stream vorstellen. RxJS bietet ein sehr umfangreiches Tool-Set zum Verwalten dieser Streams.

Wo fangen RxJS und Redux ab? In Redux aktualisieren Sie Ihren Status mit Aktionen und diese Aktionen können natürlich als Streams behandelt werden. Mit einer Middleware wie redux-beobachtbar (müssen Sie nicht) können Sie Ihre sogenannte "Geschäftslogik" reaktiv implementieren. Eine andere Sache ist, dass Sie aus Ihrem Redux-Speicher ein Observable erstellen können, was manchmal einfacher ist als die Verwendung eines Enhancers.

mdikici
quelle
2

Um es kurz zu machen:

Redux: Flux-inspirierte Bibliothek für das State Management .

RxJS: Es handelt sich um eine weitere Javascript-Bibliothek, die auf der Philosophie der reaktiven Programmierung basiert und zum Umgang mit "Streams" (Observables usw.) verwendet wird [Lesen Sie mehr über reaktive Programmierung, um die Stream-Konzepte zu verstehen].

Krishna Ganeriwal
quelle
1

Ich wollte nur einige pragmatische Unterschiede zu dem von Redux inspirierten RxJS-Code hinzufügen.

Ich habe jeden Aktionstyp einer Subject-Instanz zugeordnet. Jede zustandsbehaftete Komponente verfügt über ein Betreff, das dann einer Reduzierungsfunktion zugeordnet wird. Alle Reduzierungsströme werden mit dem Status kombiniert mergeund geben ihn dann aus scan. Der Standardwert wird mit startWithkurz vor dem festgelegt scan. Ich habe publishReplay(1)für Staaten verwendet, könnte es aber später entfernen.

Die Funktion "Reale Pure Rendering" besteht darin, nur dort zu platzieren, wo Sie Ereignisdaten erzeugen, indem Sie alle Produzenten / Subjekte einsenden.

Wenn Sie untergeordnete Komponenten haben, müssen Sie beschreiben, wie diese Zustände in Ihren kombiniert werden. combineLatestkönnte ein guter Ausgangspunkt dafür sein.

Bemerkenswerte Unterschiede in der Implementierung:

  • Keine Middleware, nur RXJS-Operatoren. Ich denke, das ist die größte Kraft und Schwäche. Sie können immer noch Konzepte ausleihen, aber es fällt mir schwer, Hilfe von Schwestergemeinschaften wie redux und cycle.js zu erhalten, da dies eine weitere benutzerdefinierte Lösung ist. Deshalb muss ich in diesem Text "Ich" anstelle von "Wir" schreiben.

  • Kein Schalter / Fall oder Zeichenfolgen für Aktionstypen. Sie haben eine dynamischere Möglichkeit, Aktionen zu trennen.

  • rxjs kann an anderer Stelle als Tool verwendet werden und ist nicht in der Statusverwaltung enthalten.

  • Weniger Produzenten als Aktionstypen (?). Ich bin mir nicht sicher, aber Sie können viele Reaktionen in übergeordneten Komponenten haben, die untergeordnete Komponenten abhören. Das bedeutet weniger imperativen Code und weniger Komplexität.

  • Sie besitzen die Lösung. Kein Rahmen erforderlich. Gut und schlecht. Sie werden sowieso Ihr eigenes Framework schreiben.

  • Es ist viel fraktaler und Sie können Änderungen aus einem Unterbaum oder mehreren Teilen des App-Statusbaums problemlos abonnieren.

    • Ratet mal, wie einfach es ist, Epen wie Redux-Observavble zu machen? Wirklich einfach.

Ich arbeite auch an viel größeren Vorteilen, bei denen die untergeordneten Komponenten als Streams beschrieben werden. Dies bedeutet, dass wir den übergeordneten und untergeordneten Status in den Reduzierungen nicht erfassen müssen, da wir die Zustände basierend auf der Komponentenstruktur nur ("nur") rekursiv kombinieren können.

Ich denke auch darüber nach, React zu überspringen und mit Snabbdom oder etwas anderem zu arbeiten, bis React besser mit reaktiven Zuständen umgeht. Warum sollten wir unseren Staat nach oben aufbauen, um ihn wieder über Requisiten zu zerlegen? Also werde ich versuchen, mit Snabbdom eine Version 2 dieses Musters zu erstellen.

Hier ist ein erweitertes, aber kleines Snippet, in dem die Datei state.ts den Statusstrom erstellt. Dies ist der Status der Ajax-Form-Komponente, der ein Objekt aus Feldern (Eingaben) mit Validierungsregeln und CSS-Stilen erhält. In dieser Datei verwenden wir nur die Feldnamen (Objektschlüssel), um alle untergeordneten Status in den Formularstatus zu kombinieren.

export default function create({
  Observable,
  ajaxInputs
}) {
  const fieldStreams = Object.keys(ajaxInputs)
  .map(function onMap(fieldName) {
    return ajaxInputs[fieldName].state.stream
    .map(function onMap(stateData) {
      return {stateData, fieldName}
    })
  })

  const stateStream = Observable.combineLatest(...fieldStreams)
  .map(function onMap(fieldStreamDataArray) {
    return fieldStreamDataArray.reduce(function onReduce(acc, fieldStreamData) {
    acc[fieldStreamData.fieldName] = fieldStreamData.stateData
    return acc
  }, {})
  })

  return {
    stream: stateStream
  }
}

Obwohl der Code für sich genommen möglicherweise nicht viel aussagt, zeigt er, wie Sie den Status nach oben aufbauen und wie Sie problemlos dynamische Ereignisse erzeugen können. Der zu zahlende Preis ist, dass Sie einen anderen Codestil verstehen müssen. Und ich liebe es, diesen Preis zu zahlen.

Marcus Rådell
quelle
Es ist ein Jahr später, ich habe gerade Ihre Antwort gefunden und denke, dass sie noch gültig ist! Ich habe etwas Ähnliches getan und stimme all Ihren Punkten zu. Aber trotzdem eine Frage: Denken Sie heute noch dasselbe oder sind Sie seitdem weitergezogen?
Xceno
1
Ich muss die Kritik an Switch / Case- und Aktionstypen in Redux überarbeiten. Ich codiere immer noch auf die gleiche Weise, versuche aber, wie man es serverseitig zum Laufen bringt. Wenn es um React-Code geht, habe ich es geschafft, ein kleines Util zu erstellen, das beim Erstellen der Reduzierer / Updater hilft. Also mache ich immer noch das Gleiche, aber ein bisschen ausgefeilter. Die größte Änderung besteht darin, dass ich jeden Blattknoten den Stream auf componentDidMount abonnieren und mich auf componentDidUnmount abmelden lasse. Ich möchte auch eine reaktive Service-Schicht erhalten, die im Frontend und Backend funktioniert. Dort Fortschritte machen.
Marcus Rådell