Unsere Datenschutzrichtlinie wird in Kürze aktualisiert. Bitte sehen Sie sich die Vorschau an.

ReactJS lernen

Datenfluss mit Redux

Testen Sie unsere 2016 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
Redux ist eine Bibliothek zur Koordination des Datenflusses und zur Verwaltung des gesamten Applikationszustands. Lernen Sie, welche Ähnlichkeiten zu Flux diese Bibliothek aufweist und wie Sie sie einsetzen.
14:01

Transkript

Das Prinzip des unidirektionalen Datenflusses ist allgemein anerkannt. Die Flux-Architektur im Speziellen unterliegt jedoch einigen Kritikpunkten. Beispielsweise kann der Dispatcher als ein Objekt gesehen werden, was zusätzliche Komplexität ohne entsprechenden Nutzen schafft. Redux ist eine Bibliothek, die sich auch am Prinzip des unidirektionalen Datenflusses orientiert, aber einige Vereinfachungen im Vergleich zu Flux beinhaltet. Die drei grundlegenden Bestandteile von Redux sind Actions, sogenannte Reducer-Funktionen, und ein globaler Store. Actions sind wie bei Flux einfache Objekte, die nur einen Typen definieren müssen und einem Event entsprechen. Die Reducer-Funktionen sind einfache Funktionen, die die Logik beinhalten, um auf Änderungen im Zustand zu reagieren. Das heißt also, ein Reducer bekommt als Argumente den aktuellen Zustand sowie die eintretende Aktion, und muss mit diesen Informationen den Zustand der Applikation berechnen. Der globale Store enthält den Zustand der gesamten Applikation und ist außerdem für das Dispatching zuständig. Das heißt, sobald eine Aktion eintritt, muss der Store die Verarbeitung dieser Aktion an den entsprechenden Reducer delegieren. Diese Konstellation bringt einige Vorteile mit sich. Beispielsweise bedeutet der globale Store, dass sich der Gesamtzustand der Anwendung an einem Ort befindet. Man spricht hier auch von Single Point of Truth. Redux ist nicht auf die Nutzung mit React beschränkt, aber gut dafür geeignet. In diesem Video werden wir das Grundgerüst für Redux aufbauen, also Aktionen und Reducer definieren, und auf der Konsole testen, wie Zustandsänderungen ablaufen. Zuerst wollen wir die Aktionen definieren. Wir definieren also für jedes Event, das auftreten kann, erstmal eine Konstante. Beispielsweise ADD_PRODUCT, um eine neues Produkt hinzuzufügen, REMOVE_PRODUCT, um ein Produkt zu entfernen, TOGGLE_WATCHED, um auf einem bestehenden Produkt den Beobachtungsstatus zu ändern. Für das Formular, um ein neues Produkt hinzuzufügen, brauchen wir die CHANGE_TITLE_FORM für den aktuellen Titel im Textfeld, CHANGE_DESCRIPTION_FORM für die aktuelle Beschreibung des Produkts, CHANGE_CATEGORY_FORM, um die Kategorie ändern zu können, TOGGLE_WATCHED_FORM für den initialen Beobachtungsstatus, und CLEAR_FORM, um den Inhalt des Formulars wieder zu löschen. Das sind aber in dieser Form noch keine fertigen Aktionen, sondern bisher nur die Aktionstypen. Um Aktionen zu produzieren, definieren wir uns einige sogenannte action creators. Das sind ganz einfache Funktionen, die ein Objekt definieren beziehungsweise ein Objekt zurückgeben, das mindestens einen type haben muss. Und als type verwenden wir eine der Konstanten, die wir oben definiert haben. Hier beispielsweise definieren wir die Funktion addProduct. Diese hat als type: ADD_PRODUCT, die Konstante von oben. Und zusätzlich können wir aber noch weitere Informationen in dieser Aktion mitgeben. Beispielsweise beim Fall ADD_PRODUCT das product, dass wir in diesem Fall erstellen möchten. Bei REMOVE_PRODUCT beispielsweise geben wir einen Index mit, damit wir wissen, welches Product wir später entfernen können. Diese Funktionen müssen aber natürlich kein Argument entgegennehmen. Beispielsweise bei clearForm geben wir einfach nur den type: CLEAR_FORM mit, weil wir auch ohne weitere Informationen wissen, welche Formularfelder wir in diesem Fall leeren müssen. Nachdem wir bereits alle Aktionen und Action-Creators definiert haben, können wir direkt zu den Reducers übergehen. Bevor man mit dem tatsächlichen Programmieren der Reducers beginnt, ist es immer sehr hilfreich, sich kurz darüber Gedanken zu machen, welche Datenstruktur wir eigentlich haben, wenn wir an den Zustand unserer Applikation denken. Also welche Daten müssen im Zustand vorhanden sein und wie sollen diese angeordnet sein? Der Gesamtzustand unserer Applikation kann im Grunde genommen in zwei von einander unabhängige Teile unterteilt werden. Wir haben einerseits das Formular, um ein neues Produkt hinzuzufügen. Das beinhaltet einerseits ein Feld für den Titel, einerseits für die Beschreibung, für die Kategorie, und für den initialen Beobachtungsstaus, sowie einen Button, um dieses Formular zu leeren. Andererseits haben wir ein Listing der aktuellen Produkte, das einfach ein Array entgegen nimmt und dieses Array von Produkten darstellt. Das heißt, wir können schonmal mit dem Gedanken beginnen, dass wir zwei Reducer brauchen. Und an dieser Stelle können wir mit dem Reducer beginnen, der für das Formular zuständig ist. Der Reducer hat die Form, dass er zwei Argumente entgegennimmt, nämlich einerseits den aktuellen Zustand, state, und andererseits eine action, die gerade eintrifft. Aus der Kombination dieser beiden Werte, muss dann der neue Zustand errechnet werden. Den state können wir schonmal mit einem leeren Objekt vorbelegen. Denn gleich zu Beginn, also zur Initialisierung von Redux werden alle Reducer einmal mit einem leeren State aufgerufen. Und dementsprechend können wir als Initial-State für unser Formular ein leeres Objekt zurückgeben, das heißt leere Formularfelder. Der grundlegende Ablauf im Reducer ist nun, dass wir mit einem switch-Statement vorgehen können, und überprüfen müssen, um welche Art von Aktion es sich gerade handelt. Wie gerade schon gesagt: Bei der Initialisierung wird diese Funktion ohne Parameter aufgerufen. Das heißt, beim allerersten Aufruf würden wir gleich in den default Case springen und einen leeren State returnen. Das heißt, diesen Fall haben wir schonmal abgedeckt. Ansonsten können wir uns mal den Case CHANGE_TITLE_FORM genauer ansehen. Wir haben hier oben einmal alle Actions importiert, aus der Datei actions über die Variable, groß geschrieben, ACTIONS. Deshalb können wir jetzt hier den Case überprüfen ACTIONS.CHANGE_TITLE_FORM. Das heißt, in dem Moment, in dem wir in den Case ACTIONS.CHANGE_TITLE_FORM hineinspringen, also in diese Zeile, haben wir folgenden Situation. Wir haben einen gewissen State gegeben. Wir wissen, dass gerade der Titel im Formularfeld geändert wurde. Und das müssen wir jetzt im aktuellen State widerspiegeln. Wir können jetzt also die Funktion Object.assign verwenden. Diese macht Folgendes. Sie nimmt hier ein leeres Objekt, kopiert die Eigenschaften des aktuellen state auf dieses leere Objekt, und zusätzlich kopiert es noch die Eigenschaften von diesem Objekts, das wir hier manuell angeben, auf das Resultat dieses ersten Kopiervorgangs. Nämlich sagen wir, nimm den aktuellen state und überschreibe jetzt aber den title, und zwar mit dem, was in action.text drinsteht. Und wenn wir nochmal einen kurzen Blick in die actions.js werfen, sehen wir, dass unsere Action vom Typ CHANGE_TITLE_FORM eine Eigenschaft namens text enthält, und zwar mit dem neuen Text, der in das Title-Formular eingegeben wurde. Dementsprechend können wir hier auf action.text zugreifen. Und schon haben wir den neuen State berechnet für den Fall CHANGE_TITLE_FORM. An dieser Stelle, also in den Reducer-Funktionen ist es sehr wichtig, dass wir nicht das Eingabe-State-Objekt verändern und zurückgeben, sondern ein neues Objekt erstellen. Deshalb benutzen wir hier auch Object.assign. Analog dazu sind die Cases für CHANGE_DESCRIPTION_FORM, CHANGE_CATEGORY_FORM, und TOGGLE_WATCHED_FORM. Hier wird aber kein Text gesetzt, sondern einfach der watched-Zustand aus dem aktuellen State negiert. Für den Fall CLEAR_FORM können wir einfach ein leeres Objekt zurückgeben, damit die Formularfelder geleert werden. Und schon haben wir unseren ersten Reducer geschrieben. Jetzt benötigen wir noch einen zweiten Reducer für die Produktliste. Dieser benötigt als State einfach nur eine Liste mit den aktuellen Produkten. Hier initialisieren wir gleich mit einem Startprodukt mit title: 'prod1' und description: 'prod2', damit das Ganze beim initialen Rendern nicht ganz so leer aussieht. Aber die Grundstruktur ist auch bei diesem Reducer gleich. Wir haben ein state, wir haben eine action. Und im Rumpf des Reducers führen wir eine Fallunterscheidung durch nach action.type und müssen jetzt die verschiedenen Cases abdecken. Wenn ein Produkt hinzugefügt wird, können wir das einfach in den aktuellen State konkatenieren. Wenn ein Produkt entfernt wird, dann können wir aus der Aktion den Index des zu entfernenden Produkts abfragen und mit dem filter-Befehl aus dem aktuellen State filtern. Und wenn der watched-Zustand eines bestehenden Produkts geändert werden soll, können wir die map-Funktion auf dem State aufrufen. Und an der Stelle, also an dem Index, an dem beim Produkt der watched-Zustand geändert werden soll, können wir ein neues Produkt returnen. Auch hier verwenden wir Object.assign, damit wir ein neues Produkt erstellen. Wir kopieren also auf ein leeres Objekt die Eigenschaften des aktuell betrachteten Produkts p, und zusätzlich den neuen watched-Zustand. Übrigens sind auch bei diesen beiden Cases, nämlich REMOVE_PRODUCT und ADD-PRODUCT, absichtlich die Funktionen concat und filter verwendet worden, weil auch diese tatsächlich neue Arrays erstellen, und nicht den Zustand des aktuellen Arrays verändern. Es ist wichtig, dass Reducer tatsächlich neue Objekte zurückliefern, weil Reducer-Funktionen sogenannte pure Funktionen sein sollen. Das heißt, sie dürfen nicht mit Seiteneffekten behaftet sein und sollten immer mit neuen Objekten arbeiten. Schließlich können wir die Methode combineReducers verwenden, die wir aus dem Paket redux erhalten, das passiert hier. Dieser können wir ein Objekt mitgeben, in dem unsere beiden Reducer enthalten sind. Und schon haben wir die Reducer fertig geschrieben. Jetzt können wir sie noch exportieren. Die combineReducers-Methode wird sich einerseits darum kümmern, dass die verschiedenen Teile des gesamten States an die richtigen Teil-Reducer weitergegeben werden. Aber auch andersrum, dass die Ergebnisse beziehungsweise die Teilergebnisse dieser Teil-Reducer richtig zu einem Gesamtzustandsobjekt zusammengesetzt werden. Das heißt, wir müssen diesen neuen Code jetzt nur noch in der index.js richtig zusammensetzen. Dazu können wir die Funktion createStore aus dem redux-Paket importieren, und außerdem unsere productApp, also den Gesamt-Reducer, den wir gerade erzeugt haben. Um ein bisschen mit den Aktionen spielen zu können, importieren wir auch diese. Jetzt können wir auch schon den Store erstellen mit der createStore-Anweisung. Als Argument geben wir unseren Gesamt-Reducer zurück. Und wir lassen uns einmal initial den State auf der Konsole ausgeben. Jetzt führen wir zusätzlich noch store.subscribe aus. Und als Argument geben wir eine Funktion mit, die jedes Mal, wenn eine Zustandsänderung geschieht, den neuen Zustand auf die Konsole loggt. Jetzt können wir uns mit unseren Action-Generators, hier beispielsweise changeTitle, einige Aktionen generieren, und dann mit store.dispatch an den Store weiterleiten. Wir simulieren jetzt also einmal, dass wir die Formularfelder ausfüllen. Wir geben einen Title ein, Redux Chair. Wir geben eine Description ein, This is a really nice electronic chair!. Wir ändern die Kategorie auf Electronics. Und wir setzen das Produkt auf watched. Anschließend wollen wir einmal das Produkt hinzufügen. Damit der Store weiß, welches Produkt wir hinzufügen, können wir direkt auf seinen Zustand zugreifen, store.getState, und dann auf die addProductForm. Anschließend löschen wir noch das Formular und entfernen das erste Produkt, also unser Initialisierungsprodukt. Anschließend beenden wir noch die Subscription mit unsubscribe. Wir lassen uns das einmal von Babel zusammenbauen, und führen es aus. Da wir die eigentliche App auskommentiert haben, sehen wir gerade nichts. Aber wir wollten ja auf der Konsole sehen, ob die Dispatch-Anweisungen auch funktioniert haben. Und wir sollten an dieser Stelle den initialen State vorliegen haben. Und wir sehen, dieser State ist in zwei Teile geteilt, die genauso heißen wie unsere Teil-Reducer, nämlich einerseits addProductForm, das ist zu Beginn leer, und andererseits das products-Array, das ein Objekt enthält, nämlich mit Description und Title. Wir wollen ein Stück weiter schauen. Dann sehen wir, hier haben schonmal drei Felder der addProductForm ausgefüllt. Das passt also so weit. Wir haben hier weiterhin nur ein Product drin. An dieser Stelle haben wir schon das vierte Feld in addProductForm ausgefüllt, nämlich watched. Und einen Schritt weiter haben wir bereits das neue Product hinzugefügt. Wir sehen hier unser Initial-Product und danach das Product, das im Formular enthalten war. Noch haben wir das Formular nicht gelöscht. Das sollte an dieser Stelle passieren. Tatsächlich, das Formular ist leer. Und schließlich an letzter Stelle haben wir sowohl das Formular gelöscht als auch unser Initial-Product. Jetzt ist nur noch das mit redux hinzugefügte Product vorhanden. In diesem Video haben Sie die Grundprinzipien von Redux kennengelernt. Sie wissen nun, dass Redux auf Aktionen, Reducern, und einem globalen Store aufbaut. Sie haben außerdem erfahren, wie das Zusammenspiel aus diesen Elementen funktioniert.

ReactJS lernen

Sehen Sie, wie Ihre Anwendung mit der Hilfe von ReactJS von einem virtuellen DOM (Document Object Model) profitiert.

2 Std. 20 min (19 Videos)
Derzeit sind keine Feedbacks vorhanden...
 
Exklusiv für Abo-Kunden
Erscheinungsdatum:05.08.2016

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!