Skalierung mit Reducer und Context
Reducer ermöglichen es, die Aktualisierungslogik des Zustands einer Komponente zu konsolidieren. Context ermöglicht es, Informationen tief in andere Komponenten zu übergeben. Sie können Reducer und Context kombinieren, um den Zustand eines komplexen Bildschirms zu verwalten.
Sie werden lernen
- Wie man einen Reducer mit Context kombiniert
- Wie man das Übergeben von Zustand und Dispatch über Props vermeidet
- Wie man Context- und Zustandslogik in einer separaten Datei hält
Kombination eines Reducers mit Context
In diesem Beispiel ausder Einführung zu Reducernwird der Zustand von einem Reducer verwaltet. Die Reducer-Funktion enthält die gesamte Zustandsaktualisierungslogik und wird am Ende dieser Datei deklariert:
Ein Reducer hilft, Event-Handler kurz und prägnant zu halten. Wenn Ihre App jedoch wächst, könnten Sie auf eine weitere Schwierigkeit stoßen.Derzeit sind dertasks-Zustand und diedispatch-Funktion nur in der oberstenTaskApp-Komponente verfügbar.Damit andere Komponenten die Aufgabenliste lesen oder ändern können, müssen Sie den aktuellen Zustand und die Event-Handler, die ihn ändern, explizitnach unten weitergeben, als Props.
Zum Beispiel gibtTaskAppeine Liste von Aufgaben und die Event-Handler anTaskListweiter:
UndTaskListgibt die Event-Handler anTaskweiter:
In einem kleinen Beispiel wie diesem funktioniert das gut, aber wenn Sie Dutzende oder Hunderte von Komponenten dazwischen haben, kann das Weitergeben des gesamten Zustands und aller Funktionen ziemlich frustrierend sein!
Deshalb möchten Sie möglicherweise, als Alternative zum Weitergeben über Props, sowohl dentasks-Zustand als auch diedispatch-Funktionin Context setzen.Auf diese Weise kann jede Komponente unterhalb vonTaskAppim Baum die Aufgaben lesen und Aktionen dispatch, ohne das wiederholte "Prop-Drilling".
So können Sie einen Reducer mit Context kombinieren:
- ErstellenSie den Kontext.
- FügenSie State und Dispatch in den Kontext ein.
- VerwendenSie den Kontext an beliebiger Stelle im Baum.
Schritt 1: Kontext erstellen
DeruseReducer-Hook gibt die aktuelletasks-Liste und diedispatch-Funktion zurück, mit der Sie sie aktualisieren können:
Um sie den Baum hinunter zu übergeben, werden Siezwei separate Kontexte erstellen:
TasksContextstellt die aktuelle Aufgabenliste bereit.TasksDispatchContextstellt die Funktion bereit, mit der Komponenten Aktionen dispatchen können.
Exportieren Sie sie aus einer separaten Datei, damit Sie sie später aus anderen Dateien importieren können:
Hier übergeben Sienullals Standardwert an beide Kontexte. Die tatsächlichen Werte werden von derTaskApp-Komponente bereitgestellt.
Schritt 2: State und Dispatch in den Kontext einfügen
Jetzt können Sie beide Kontexte in IhrerTaskApp-Komponente importieren. Nehmen Sie die vonuseReducer()zurückgegebenentasks und dispatchundstellen Sie sie dem gesamten darunterliegenden Baum zur Verfügung:
Vorübergehend übergeben Sie die Informationen sowohl über Props als auch über den Kontext:
Im nächsten Schritt werden Sie die Weitergabe von Props entfernen.
Schritt 3: Verwenden Sie Context überall im Baum
Jetzt müssen Sie die Aufgabenliste oder die Event-Handler nicht mehr durch den Baum weitergeben:
Stattdessen kann jede Komponente, die die Aufgabenliste benötigt, sie aus demTasksContextlesen:
Um die Aufgabenliste zu aktualisieren, kann jede Komponente diedispatch-Funktion aus dem Kontext lesen und sie aufrufen:
DieTaskApp-Komponente gibt keine Event-Handler weiter, und dieTaskList-Komponente gibt ebenfalls keine Event-Handler an dieTask-Komponente weiter.Jede Komponente liest den Kontext, den sie benötigt:
Der State „lebt“ weiterhin in der oberstenTaskApp-Komponente, verwaltet mituseReducer.Aber ihretasksunddispatchsind nun für jede Komponente weiter unten im Baum verfügbar, indem diese Kontexte importiert und verwendet werden.
Die gesamte Verkabelung in eine einzige Datei verschieben
Sie müssen das nicht tun, aber Sie könnten die Komponenten weiter entrümpeln, indem Sie sowohl Reducer als auch Kontext in eine einzige Datei verschieben. Derzeit enthältTasksContext.jsnur zwei Kontextdeklarationen:
Diese Datei wird gleich überfüllt sein! Sie werden den Reducer in dieselbe Datei verschieben. Dann deklarieren Sie eine neueTasksProvider-Komponente in derselben Datei. Diese Komponente wird alle Teile miteinander verbinden:
- Sie verwaltet den State mit einem Reducer.
- Sie stellt beide Kontexte für darunterliegende Komponenten bereit.
- Sienimmt children als Prop, sodass Sie ihr JSX übergeben können.
Dies entfernt die gesamte Komplexität und Verkabelung aus IhrerTaskApp-Komponente:
Sie können auch Funktionen exportieren, dieden Kontext verwenden aus TasksContext.js:
Wenn eine Komponente den Kontext lesen muss, kann sie dies über diese Funktionen tun:
Dies ändert das Verhalten in keiner Weise, ermöglicht es Ihnen aber, diese Kontexte später weiter aufzuteilen oder diesen Funktionen Logik hinzuzufügen.Jetzt befindet sich die gesamte Kontext- und Reducer-Verknüpfung inTasksContext.js. Dadurch bleiben die Komponenten sauber und übersichtlich, konzentriert auf das, was sie anzeigen, anstatt darauf, woher sie die Daten beziehen:
Sie können sichTasksProviderals einen Teil des Bildschirms vorstellen, der weiß, wie mit Aufgaben umzugehen ist,useTasksals eine Möglichkeit, sie zu lesen, unduseTasksDispatchals eine Möglichkeit, sie von jeder Komponente weiter unten im Baum aus zu aktualisieren.
Hinweis
Funktionen wieuseTasksunduseTasksDispatchwerdenCustom Hooks genannt.Deine Funktion gilt als Custom Hook, wenn ihr Name mitusebeginnt. Dadurch kannst du andere Hooks, wieuseContext, darin verwenden.
Wenn deine App wächst, kannst du viele solcher Kontext-Reducer-Paare haben. Dies ist eine leistungsstarke Methode, um deine App zu skalieren und denState nach oben zu heben, ohne zu viel Aufwand zu betreiben, wenn du auf Daten tief im Baum zugreifen möchtest.
Zusammenfassung
- Sie können Reducer mit Context kombinieren, um jeder Komponente zu ermöglichen, den darüber liegenden Zustand zu lesen und zu aktualisieren.
- Um den Zustand und die Dispatch-Funktion für darunter liegende Komponenten bereitzustellen:
- Erstellen Sie zwei Contexts (einen für den Zustand und einen für die Dispatch-Funktionen).
- Stellen Sie beide Contexts von der Komponente bereit, die den Reducer verwendet.
- Verwenden Sie den jeweiligen Context in Komponenten, die ihn lesen müssen.
- Sie können die Komponenten weiter entrümpeln, indem Sie die gesamte Verkabelung in eine Datei verschieben.
- Sie können eine Komponente wie
TasksProviderexportieren, die den Context bereitstellt. - Sie können auch benutzerdefinierte Hooks wie
useTasksunduseTasksDispatchexportieren, um ihn zu lesen.
- Sie können eine Komponente wie
- Sie können viele solcher Context-Reducer-Paare in Ihrer App haben.
