Redux · Eine Einführung

Veröffentlicht: 2022-03-10
Kurze Zusammenfassung ↬ Redux ist heutzutage eine der heißesten Bibliotheken in der Frontend-Entwicklung. Viele Menschen sind jedoch verwirrt darüber, was es ist und welche Vorteile es hat. Wie in der Dokumentation angegeben, ist Redux ein vorhersagbarer Zustandscontainer für JavaScript-Apps . Um es anders auszudrücken, es handelt sich eher um eine Anwendungsdatenflussarchitektur als um eine traditionelle Bibliothek oder ein Framework wie Underscore.js und AngularJS.

Redux ist heutzutage eine der heißesten Bibliotheken in der Frontend-Entwicklung. Viele Menschen sind jedoch verwirrt darüber, was es ist und welche Vorteile es hat.

Wie in der Dokumentation angegeben, ist Redux ein vorhersagbarer Zustandscontainer für JavaScript-Apps. Um es anders auszudrücken, es handelt sich eher um eine Anwendungsdatenflussarchitektur als um eine traditionelle Bibliothek oder ein Framework wie Underscore.js und AngularJS.

Weiterführende Literatur zu SmashingMag

  • Warum Sie React Native für Ihre mobile App in Betracht ziehen sollten
  • Testautomatisierung für Apps, Spiele und das mobile Web
  • Serverseitiges Rendern mit React, Node und Express
  • Hinweise zur Client-gerenderten Barrierefreiheit

Redux wurde ungefähr im Juni 2015 von Dan Abramov erstellt. Es wurde von Facebooks Flux und der funktionalen Programmiersprache Elm inspiriert. Redux wurde aufgrund seiner Einfachheit, seiner geringen Größe (nur 2 KB) und seiner großartigen Dokumentation sehr schnell populär . Wenn Sie erfahren möchten, wie Redux intern funktioniert, und tief in die Bibliothek eintauchen möchten, sollten Sie sich Dans kostenlosen Kurs ansehen.

Mehr nach dem Sprung! Lesen Sie unten weiter ↓

Redux wird hauptsächlich für die Verwaltung des Anwendungsstatus verwendet. Zusammenfassend verwaltet Redux den Status einer gesamten Anwendung in einem einzigen unveränderlichen Statusbaum (Objekt), der nicht direkt geändert werden kann. Wenn sich etwas ändert, wird ein neues Objekt erstellt (unter Verwendung von Aktionen und Reduzierungen). Wir gehen weiter unten im Detail auf die Kernkonzepte ein.

Wie unterscheidet es sich von MVC und Flux?

Um etwas Perspektive zu geben, nehmen wir das klassische Model-View-Controller (MVC)-Muster, da die meisten Entwickler damit vertraut sind. In der MVC-Architektur gibt es eine klare Trennung zwischen Daten (Modell), Präsentation (View) und Logik (Controller). Dabei gibt es vor allem bei großen Anwendungen ein Problem: Der Datenfluss ist bidirektional. Dies bedeutet, dass eine Änderung (eine Benutzereingabe oder eine API-Antwort) den Status einer Anwendung an vielen Stellen im Code beeinflussen kann – beispielsweise bei der bidirektionalen Datenbindung. Das kann schwer zu warten und zu debuggen sein.

Flux ist Redux sehr ähnlich. Der Hauptunterschied besteht darin, dass Flux über mehrere Speicher verfügt, die den Status der Anwendung ändern, und diese Änderungen als Ereignisse überträgt. Komponenten können diese Ereignisse abonnieren, um sie mit dem aktuellen Status zu synchronisieren. Redux hat keinen Dispatcher , der in Flux verwendet wird, um Payloads an registrierte Callbacks zu senden. Ein weiterer Unterschied bei Flux besteht darin, dass viele Varianten verfügbar sind, was zu Verwirrung und Inkonsistenz führt.

Vorteile von Redux

Sie fragen sich vielleicht: „Warum sollte ich Redux verwenden?“ Tolle Frage. Die Verwendung von Redux in Ihrer nächsten Anwendung bietet einige Vorteile:

  • Vorhersagbarkeit des Ergebnisses
    Es gibt immer eine Quelle der Wahrheit, den Store, ohne Verwirrung darüber, wie der aktuelle Status mit Aktionen und anderen Teilen der Anwendung synchronisiert werden kann.
  • Wartbarkeit
    Ein vorhersehbares Ergebnis und eine strenge Struktur machen den Code leichter zu warten.
  • Organisation
    Redux ist strenger bei der Organisation von Code, wodurch der Code konsistenter und für ein Team einfacher zu bearbeiten ist.
  • Server-Rendering
    Dies ist sehr nützlich, insbesondere für das anfängliche Rendern, um eine bessere Benutzererfahrung oder Suchmaschinenoptimierung zu erzielen. Übergeben Sie einfach den auf dem Server erstellten Speicher an die Clientseite.
  • Entwicklerwerkzeuge
    Entwickler können alles, was in der App vor sich geht, in Echtzeit verfolgen, von Aktionen bis hin zu Statusänderungen.
  • Gemeinschaft und Ökosystem
    Dies ist ein großes Plus, wenn Sie eine Bibliothek oder ein Framework lernen oder verwenden. Eine Community hinter Redux macht die Nutzung noch attraktiver.
  • Einfaches Testen
    Die erste Regel beim Schreiben von testbarem Code besteht darin, kleine Funktionen zu schreiben, die nur eine Sache tun und die unabhängig sind. Der Code von Redux besteht hauptsächlich aus Funktionen, die genau das sind: klein, rein und isoliert.

Funktionale Programmierung

Wie bereits erwähnt, wurde Redux auf funktionalen Programmierkonzepten aufgebaut. Das Verständnis dieser Konzepte ist sehr wichtig, um zu verstehen, wie und warum Redux so funktioniert, wie es funktioniert. Sehen wir uns die grundlegenden Konzepte der funktionalen Programmierung noch einmal an:

  • Es ist in der Lage, Funktionen als erstklassige Objekte zu behandeln.
  • Es ist in der Lage, Funktionen als Argumente zu übergeben.
  • Es ist in der Lage, den Fluss mithilfe von Funktionen, Rekursionen und Arrays zu steuern.
  • Es ist in der Lage, reine, rekursive, höherwertige, Abschluss- und anonyme Funktionen zu verwenden.
  • Es ist in der Lage, Hilfsfunktionen wie Map, Filter und Reduce zu verwenden.
  • Es ist in der Lage, Funktionen miteinander zu verketten.
  • Der Zustand ändert sich nicht (dh er ist unveränderlich).
  • Die Reihenfolge der Codeausführung ist nicht wichtig.

Die funktionale Programmierung ermöglicht es uns, saubereren und modulareren Code zu schreiben. Indem wir kleinere und einfachere Funktionen schreiben, die in Umfang und Logik isoliert sind, können wir den Code viel einfacher testen, warten und debuggen. Jetzt werden diese kleineren Funktionen zu wiederverwendbarem Code , und das ermöglicht es Ihnen, weniger Code zu schreiben, und weniger Code ist eine gute Sache. Die Funktionen können kopiert und überall ohne Änderung eingefügt werden. Funktionen, die im Umfang isoliert sind und nur eine Aufgabe ausführen, hängen weniger von anderen Modulen in einer App ab, und diese reduzierte Kopplung ist ein weiterer Vorteil der funktionalen Programmierung.

01-funktionale-programmierung-opt-vorschau
Funktionales Programmierbeispiel (Bild: Tanya Bachuk) (Große Version anzeigen)

Reine Funktionen, anonyme Funktionen, Closures, Funktionen höherer Ordnung und Methodenketten werden Ihnen sehr häufig begegnen, wenn Sie mit funktionalem JavaScript arbeiten. Redux verwendet stark reine Funktionen, daher ist es wichtig zu verstehen, was sie sind.

Reine Funktionen geben basierend auf den ihnen übergebenen Argumenten einen neuen Wert zurück. Sie ändern keine bestehenden Objekte; stattdessen geben sie einen neuen zurück. Diese Funktionen verlassen sich nicht auf den Status, aus dem sie aufgerufen werden, und sie geben nur ein und dasselbe Ergebnis für jedes bereitgestellte Argument zurück. Aus diesem Grund sind sie sehr vorhersehbar.

Da reine Funktionen keine Werte ändern, haben sie keinen Einfluss auf den Umfang oder beobachtbare Nebenwirkungen, und das bedeutet, dass sich ein Entwickler nur auf die Werte konzentrieren kann, die die reine Funktion zurückgibt.

Wo kann Redux verwendet werden?

Die meisten Entwickler assoziieren Redux mit React, aber es kann mit jeder anderen Ansichtsbibliothek verwendet werden. Beispielsweise können Sie Redux mit AngularJS, Vue.js, Polymer, Ember, Backbone.js und Meteor verwenden. Redux plus React ist jedoch immer noch die häufigste Kombination. Stellen Sie sicher, dass Sie React in der richtigen Reihenfolge lernen: Der beste Leitfaden ist der von Pete Hunt, der sehr hilfreich für Entwickler ist, die mit React beginnen und mit allem, was im Ökosystem vor sich geht, überfordert sind. JavaScript-Müdigkeit ist eine berechtigte Sorge unter Front-End-Entwicklern, sowohl neuen als auch erfahrenen, also nehmen Sie sich die Zeit, React oder Redux richtig und in der richtigen Reihenfolge zu lernen.

Einer der Gründe, warum Redux großartig ist, ist sein Ökosystem. Es sind so viele Artikel, Tutorials, Middleware, Tools und Boilerplates verfügbar. Persönlich verwende ich die Boilerplate von David Zukowski, weil sie alles hat, was man braucht, um eine JavaScript-Anwendung zu bauen, mit React, Redux und React Router. Ein Wort der Vorsicht: Versuchen Sie, beim Erlernen neuer Frameworks wie React und Redux keine Boilerplates und Starterkits zu verwenden. Es wird es noch verwirrender machen, weil Sie nicht verstehen werden, wie alles zusammenarbeitet. Lernen Sie es zuerst und erstellen Sie eine sehr einfache App, idealerweise als Nebenprojekt, und verwenden Sie dann Boilerplates für Produktions-Apps, um Zeit zu sparen.

Bauteile von Redux

Redux-Konzepte mögen kompliziert oder ausgefallen klingen, aber sie sind einfach. Denken Sie daran, dass die Bibliothek nur 2 KB groß ist. Redux besteht aus drei Bauteilen: Actions, Store und Reducers.

02-redux-dataflow-opt-preview
Redux-Datenfluss (Bild: Tanya Bachuk) (Große Version anzeigen)

Lassen Sie uns besprechen, was jeder tut.

Aktionen

Kurz gesagt, Aktionen sind Ereignisse. Aktionen senden Daten von der Anwendung (Benutzerinteraktionen, interne Ereignisse wie API-Aufrufe und Formularübermittlungen) an den Store. Der Store erhält Informationen nur aus Aktionen. Interne Aktionen sind einfache JavaScript-Objekte mit einer type Eigenschaft (normalerweise konstant), die den Aktionstyp und die Nutzlast der an den Store gesendeten Informationen beschreibt.

 { type: LOGIN_FORM_SUBMIT, payload: {username: 'alex', password: '123456'} }

Aktionen werden mit Aktionserstellern erstellt. Das klingt selbstverständlich, ich weiß. Sie sind nur Funktionen, die Aktionen zurückgeben.

 function authUser(form) { return { type: LOGIN_FORM_SUBMIT, payload: form } }

Das Aufrufen von Aktionen überall in der App ist also sehr einfach. Verwenden Sie die dispatch wie folgt:

 dispatch(authUser(form));

Reduzierer

Wir haben bereits besprochen, was ein Reducer in funktionalem JavaScript ist. Es basiert auf der Array-Reduce-Methode, bei der es einen Rückruf (Reducer) akzeptiert und Sie einen einzelnen Wert aus mehreren Werten, Summen von Ganzzahlen oder einer Anhäufung von Werteströmen erhalten lässt. In Redux sind Reducer (reine) Funktionen, die den aktuellen Zustand der Anwendung und eine Aktion übernehmen und dann einen neuen Zustand zurückgeben. Es ist wichtig zu verstehen, wie Reduzierer funktionieren, da sie die meiste Arbeit leisten. Hier ist ein sehr einfacher Reducer, der den aktuellen Zustand und eine Aktion als Argumente nimmt und dann den nächsten Zustand zurückgibt:

 function handleAuth(state, action) { return _.assign({}, state, { auth: action.payload }); }

Für komplexere Apps ist die Verwendung des von Redux bereitgestellten Dienstprogramms combineReducers() möglich (tatsächlich empfohlen). Es kombiniert alle Reduzierer in der App zu einem einzigen Index-Reduzierer. Jeder Reducer ist für seinen eigenen Teil des Zustands der App verantwortlich, und der Zustandsparameter ist für jeden Reducer unterschiedlich. Das combineReducers() erleichtert die Verwaltung der Dateistruktur erheblich.

Wenn ein Objekt (Zustand) nur einige Werte ändert, erstellt Redux ein neues Objekt, die Werte, die sich nicht geändert haben, beziehen sich auf das alte Objekt und es werden nur neue Werte erstellt. Das ist großartig für die Leistung. Um es noch effizienter zu machen, können Sie Immutable.js hinzufügen.

 const rootReducer = combineReducers({ handleAuth: handleAuth, editProfile: editProfile, changePassword: changePassword });

Speichern

Store ist das Objekt, das den Anwendungsstatus enthält und einige Hilfsmethoden bereitstellt, um auf den Status zuzugreifen, Aktionen auszuführen und Listener zu registrieren. Der gesamte Staat wird durch einen einzigen Laden repräsentiert. Jede Aktion gibt über Reducer einen neuen Zustand zurück. Das macht Redux sehr einfach und vorhersehbar.

 import { createStore } from 'redux'; let store = createStore(rootReducer); let authInfo = {username: 'alex', password: '123456'}; store.dispatch(authUser(authInfo));

Entwicklertools, Zeitreisen und Hot Reloading

Um die Arbeit mit Redux zu vereinfachen, insbesondere wenn Sie mit einer umfangreichen Anwendung arbeiten, empfehle ich die Verwendung von Redux DevTools. Es ist unglaublich hilfreich, da es die Änderungen des Status im Laufe der Zeit, Änderungen in Echtzeit, Aktionen und den aktuellen Status anzeigt. Dadurch sparen Sie Zeit und Mühe, indem Sie den aktuellen Status und die aktuellen Aktionen von console.log vermeiden

03-redux-dev-tools-opt-preview
Redux DevTools (Große Version anzeigen)

Redux hat eine etwas andere Implementierung von Zeitreisen als Flux. In Redux können Sie zu einem früheren Zustand zurückkehren und Ihren Zustand von diesem Punkt an sogar in eine andere Richtung lenken. Redux DevTools unterstützt die folgenden „Zeitreise“-Funktionen im Redux-Workflow (stellen Sie sich diese als Git-Befehle für Ihren Status vor):

  • Zurücksetzen : Setzt auf den Zustand zurück, mit dem Ihr Geschäft erstellt wurde
  • Revert : Kehrt zum letzten festgeschriebenen Zustand zurück
  • Sweep : Entfernt alle deaktivierten Aktionen, die Sie möglicherweise versehentlich ausgelöst haben
  • Commit : macht den aktuellen Zustand zum Anfangszustand

Die Zeitreisefunktion ist in der Produktion nicht effizient und nur für Entwicklung und Debugging vorgesehen. Dasselbe gilt für DevTools.

Redux macht das Testen viel einfacher, da es funktionales JavaScript als Basis verwendet und kleine unabhängige Funktionen einfach zu testen sind. Wenn Sie also etwas in Ihrem Statusbaum ändern müssen, importieren Sie nur einen Reducer, der für diesen Status verantwortlich ist, und testen Sie ihn isoliert.

Erstellen Sie eine App

Lassen Sie uns zum Abschluss dieser Einführung eine sehr einfache Anwendung mit Redux und React erstellen. Um es für alle einfacher zu machen, werde ich beim einfachen alten JavaScript bleiben und ECMAScript 2015 und 2016 so wenig wie möglich verwenden. Wir werden die zuvor in diesem Beitrag begonnene Anmeldelogik fortsetzen. Dieses Beispiel verwendet keine Live-Daten, da der Zweck dieser App darin besteht, zu zeigen, wie Redux den Status einer sehr einfachen App verwaltet. Wir verwenden CodePen.

1. Reaktionskomponente

Wir brauchen einige React-Komponenten und Daten. Lassen Sie uns eine einfache Komponente erstellen und auf der Seite rendern. Die Komponente wird ein Eingabefeld und eine Schaltfläche haben (es ist ein sehr einfaches Anmeldeformular). Unten fügen wir Text hinzu, der unseren Zustand darstellt:

Siehe Pen Intro to Redux von Alex Bachuk (@abachuk) auf CodePen.

Siehe Pen Intro to Redux von Alex Bachuk (@abachuk) auf CodePen.

2. Ereignisse und Aktionen

Lassen Sie uns Redux zum Projekt hinzufügen und das onClick Ereignis für die Schaltfläche verarbeiten. Sobald sich der Benutzer anmeldet, versenden wir die Aktion mit dem Typ LOGIN und dem Wert des aktuellen Benutzers. Bevor wir das tun können, müssen wir einen Store erstellen und ihm eine Reducer-Funktion als Argument übergeben. Im Moment ist der Reducer nur eine leere Funktion:

Siehe Pen Intro to Redux – Step 2. Events and Actions von Alex Bachuk (@abachuk) auf CodePen.

Siehe Pen Intro to Redux – Step 2. Events and Actions von Alex Bachuk (@abachuk) auf CodePen.

3. Reduzierstücke

Jetzt, da wir die Aktion ausgelöst haben, wird der Reduzierer diese Aktion ausführen und einen neuen Zustand zurückgeben. Lassen Sie uns die LOGIN -Aktion verarbeiten, die einen eingeloggten Status zurückgibt, und auch eine LOGOUT -Aktion hinzufügen, damit wir sie später verwenden können. Der auth Reducer akzeptiert zwei Parameter:

  1. der aktuelle Zustand (der den Standardwert hat),
  2. die Aktion.

Siehe Pen Intro to Redux – Step 3. Reducers von Alex Bachuk (@abachuk) auf CodePen.

Siehe Pen Intro to Redux – Step 3. Reducers von Alex Bachuk (@abachuk) auf CodePen.

4. Anzeige des aktuellen Status

Nachdem wir nun den Anfangszustand (den Standardwert in Reducer) und die React-Komponente fertig haben, sehen wir uns an, wie der Zustand aussieht. Eine bewährte Methode besteht darin, den Zustand auf untergeordnete Komponenten herunterzudrücken. Da wir nur eine Komponente haben, übergeben wir den Status der App als Eigenschaft an auth . Damit alles zusammenarbeitet, müssen wir den Store-Listener mit einer subscribe -Hilfsmethode registrieren, indem ReactDOM.render in eine Funktion packen und an store.subscribe() :

Siehe Pen Intro to Redux – Step 4. Displaying current state von Alex Bachuk (@abachuk) auf CodePen.

Siehe Pen Intro to Redux – Step 4. Displaying current state von Alex Bachuk (@abachuk) auf CodePen.

5. An- und abmelden

Nachdem wir jetzt Anmelde- und Abmeldeaktionshandler haben, fügen wir eine Abmeldeschaltfläche hinzu und lösen die LOGOUT -Aktion aus. Der letzte Schritt besteht darin, zu verwalten, welche Schaltfläche zum An- oder Abmelden angezeigt werden soll, indem Sie diese Anmeldung aus der Rendermethode verschieben und die Variable unten rendern:

Siehe Pen Intro to Redux – Step 5. Login/Logout von Alex Bachuk (@abachuk) auf CodePen.

Siehe Pen Intro to Redux – Step 5. Login/Logout von Alex Bachuk (@abachuk) auf CodePen.

Fazit

Redux gewinnt jeden Tag an Zugkraft. Es wurde von vielen Unternehmen (Uber, Khan Academy, Twitter) und in vielen Projekten (Apollo, WordPress' Calypso) erfolgreich in der Produktion eingesetzt. Einige Entwickler beschweren sich vielleicht, dass es viel Overhead gibt. In den meisten Fällen ist mehr Code erforderlich, um einfache Aktionen wie Schaltflächenklicks oder einfache Änderungen der Benutzeroberfläche auszuführen. Redux ist nicht für alles perfekt geeignet. Es muss ein Gleichgewicht geben. Vielleicht müssen einfache Aktionen und UI-Änderungen nicht Teil des Redux-Speichers sein und können auf Komponentenebene gepflegt werden.

Auch wenn Redux möglicherweise keine ideale Lösung für Ihre App oder Ihr Framework ist, empfehle ich dringend, es auszuprobieren, insbesondere für React-Anwendungen.

Bildnachweise auf der Titelseite: Lynn Fisher, @lynnandtonic