In dem Artikel, den wir heute übersetzen, wird erläutert, wie Containerkomponenten in React-Anwendungen erstellt werden, die sich auf den Status von Redux beziehen. Dieses Material basiert auf der Beschreibung des Zustandsverwaltungsmechanismus in React unter Verwendung des React 
-Redux-Pakets . Es wird davon ausgegangen, dass Sie bereits ein grundlegendes Verständnis der Architektur und API der Bibliotheken haben, über die wir sprechen werden. Ist dies nicht der Fall, 
lesen Sie die Dokumentation zu 
React and 
Redux .

Informationen zur Statusverwaltung in JavaScript-Anwendungen
React bietet dem Entwickler zwei Hauptmechanismen zum Übertragen von Daten an Komponenten. Dies sind Eigenschaften (Requisiten) und Zustand. Eigenschaften sind schreibgeschützt und ermöglichen es übergeordneten Komponenten, Attribute an untergeordnete Komponenten zu übergeben. Ein Status ist eine lokale Entität, die in einer Komponente gekapselt ist und sich jederzeit im Lebenszyklus der Komponente ändern kann.
Da state ein äußerst nützlicher Mechanismus zum Erstellen leistungsfähiger dynamischer React-Anwendungen ist, muss es ordnungsgemäß verwaltet werden. Derzeit gibt es mehrere Bibliotheken, die eine gut strukturierte Architektur für die Verwaltung des Anwendungszustands bereitstellen. Unter ihnen sind 
Flux , 
Redux , 
MobX .
Redux ist eine Bibliothek zum Erstellen von Containern zum Speichern des Anwendungsstatus. Es bietet dem Entwickler verständliche Tools zur Statusverwaltung, die sich vorhersehbar verhalten. Diese Bibliothek eignet sich für Anwendungen, die in reinem JavaScript geschrieben sind, sowie für Projekte, bei deren Entwicklung einige Frameworks verwendet wurden. Redux ist klein, aber Sie können zuverlässige Anwendungen schreiben, die in verschiedenen Umgebungen funktionieren.
So erstellen Sie Redux-Repositorys:
import { createStore } from 'redux'; const initialState = {    auth: { loggedIn: false } } const store = createStore((state = initialState, action) => {    switch (action.type) {        case "LOG_IN":            return { ...state, auth: { loggedIn: true } };            break;        case "LOG_OUT":            return { ...state, auth: { loggedIn: false } };            break;        default:            return state;            break;    }    }) 
React-Redux-Paket
Das React-Redux-Paket enthält React-Bindungen für den Redux-Statuscontainer, sodass die React-Anwendung extrem einfach mit dem Redux-Repository verbunden werden kann. Auf diese Weise können Sie die Komponenten einer React-Anwendung anhand ihrer Beziehung zum Repository trennen. Wir sprechen nämlich über die folgenden Arten von Komponenten:
- Präsentationskomponenten. Sie sind nur für das Erscheinungsbild der Anwendung verantwortlich und kennen den Status von Redux nicht. Sie empfangen Daten über Eigenschaften und können Rückrufe aufrufen, die auch über Eigenschaften an sie weitergeleitet werden.
- Containerkomponenten. Sie sind für den Betrieb der internen Mechanismen der Anwendung verantwortlich und interagieren mit dem Status von Redux. Sie werden häufig mit React-Redux erstellt und können Redux-Aktionen auslösen. Darüber hinaus abonnieren sie Statusänderungen.
Details zu diesem Ansatz zur Aufteilung der Verantwortung von Bauteilen finden Sie 
hier . In diesem Artikel werden wir hauptsächlich über Containerkomponenten sprechen, die mithilfe von React-Redux mit dem Redux-Status verbunden sind.
Das React-Redux-Paket verfügt über eine sehr einfache Oberfläche. Das Interessanteste an dieser Schnittstelle ist insbesondere Folgendes:
- <Provider store>- Mit dieser Option können Sie einen Wrapper für eine React-Anwendung erstellen und den Redux-Status für alle Containerkomponenten in ihrer Hierarchie verfügbar machen.
- connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])- Ermöglicht das Erstellen von Komponenten höherer Ordnung. Dies ist erforderlich, um Containerkomponenten basierend auf den grundlegenden React-Komponenten zu erstellen.
Installieren Sie react-redux, um dieses Paket wie folgt im Projekt zu verwenden:
 npm install react-redux  
Basierend auf der Annahme, dass Sie das Redux-Repository bereits für Ihre React-Anwendung konfiguriert haben, finden Sie hier ein Beispiel für die Verbindung der Anwendung mit dem Redux-Repository:
 import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import createStore from './createReduxStore'; const store = createStore(); const rootElement = document.getElementById('root'); ReactDOM.render(( <Provider store={store}>   <AppRootComponent /> </Provider> ), rootElement); 
Jetzt können Sie Containerkomponenten erstellen, die mit dem Redux-Repository verbunden sind. Dies erfolgt innerhalb der Hierarchie der 
AppRootComponent mithilfe der 
connect() API.
Wann soll connect () verwendet werden?
▍Containerkomponenten erstellen
Wie bereits erwähnt, werden mit der API react-redux 
connect() Containerkomponenten erstellt, die mit dem Redux-Repository verbunden sind. Der Speicher, zu dem Sie eine Verbindung herstellen, wird vom obersten Vorfahren der Komponente mithilfe des Kontextmechanismus "Reagieren" abgerufen. Die Funktion 
connect() wird nicht benötigt, wenn Sie nur Präsentationskomponenten erstellen.
Wenn Sie in der React-Komponente Daten aus dem Speicher empfangen müssen oder Aktionen auslösen müssen oder beides ausführen müssen, können Sie eine reguläre Komponente in eine Containerkomponente konvertieren, indem Sie sie in eine Komponente höherer Ordnung einschließen, die von 
connect() von zurückgegeben wird React-Redux. So sieht es aus:
 import React from 'react'; import { connect } from 'react-redux'; import Profile from './components/Profile'; function ProfileContainer(props) { return (   props.loggedIn     ? <Profile profile={props.profile} />     : <div>Please login to view profile.</div> ) } const mapStateToProps = function(state) { return {   profile: state.user.profile,   loggedIn: state.auth.loggedIn } } export default connect(mapStateToProps)(ProfileContainer); 
▍ Sie müssen den Redux-Speicher nicht mehr manuell abonnieren
Sie können die Containerkomponente selbst erstellen und die Komponente im Redux-Repository manuell mit dem Befehl 
store.subscribe() . Die Verwendung der Funktion 
connect() bedeutet jedoch, einige Leistungsverbesserungen und -optimierungen anzuwenden, die Sie möglicherweise nicht verwenden können, wenn Sie andere Mechanismen verwenden.
Im folgenden Beispiel versuchen wir, eine Containerkomponente manuell zu erstellen und sie durch Abonnieren mit dem Redux-Repository zu verbinden. Hier bemühen wir uns, die gleiche Funktionalität wie im vorherigen Beispiel zu implementieren.
 import React, { Component } from 'react'; import store from './reduxStore'; import Profile from './components/Profile'; class ProfileContainer extends Component { state = this.getCurrentStateFromStore() getCurrentStateFromStore() {   return {     profile: store.getState().user.profile,     loggedIn: store.getState().auth.loggedIn   } } updateStateFromStore = () => {   const currentState = this.getCurrentStateFromStore();     if (this.state !== currentState) {     this.setState(currentState);   } } componentDidMount() {   this.unsubscribeStore = store.subscribe(this.updateStateFromStore); } componentWillUnmount() {   this.unsubscribeStore(); } render() {   const { loggedIn, profile } = this.state;     return (     loggedIn       ? <Profile profile={profile} />       : <div>Please login to view profile.</div>   ) } } export default ProfileContainer; 
Die Funktion 
connect() bietet dem Entwickler außerdem zusätzliche Flexibilität, sodass Sie Containerkomponenten so konfigurieren können, dass sie dynamische Eigenschaften basierend auf den Eigenschaften erhalten, die ursprünglich an sie übergeben wurden. Dies erweist sich als sehr nützlich, um eine Auswahl aus einem Zustand basierend auf Eigenschaften zu erhalten oder um Aktionsgeneratoren mit einer bestimmten Variablen aus Eigenschaften zu verknüpfen.
Wenn Ihre React-Anwendung mehrere Redux-Repositorys verwendet, können Sie mit 
connect() auf einfache Weise das spezifische Repository angeben, mit dem die Containerkomponente verbunden werden soll.
Anatomie verbinden ()
Die vom React-Redux-Paket bereitgestellte Funktion 
connect() kann bis zu vier Argumente annehmen, von denen jedes optional ist. Nach dem Aufruf der Funktion 
connect() wird eine Komponente höherer Ordnung zurückgegeben, mit der jede React-Komponente umbrochen werden kann.
Da die Funktion eine Komponente höherer Ordnung zurückgibt, muss sie erneut aufgerufen werden, wobei die grundlegende React-Komponente übergeben wird, um sie in eine Containerkomponente zu konvertieren:
 const ContainerComponent = connect()(BaseComponent) 
Hier ist die Signatur der Funktion 
connect() :
 connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options]) 
▍ mapStateToProps-Argument
Das Argument 
mapStateToProps ist eine Funktion, die entweder ein reguläres Objekt oder eine andere Funktion zurückgibt. Wenn Sie dieses 
connect() -Argument übergeben, wird die Containerkomponente für Redux-Repository-Updates abonniert. Dies bedeutet, dass die Funktion 
mapStateToProps jedes Mal 
mapStateToProps wird, wenn sich der Status des Repositorys ändert. Wenn Sie nicht an der Überwachung von Statusaktualisierungen interessiert sind, übergeben Sie 
connect() als Wert dieses Arguments an 
undefined oder 
null .
Die Funktion 
mapStateToProps mit zwei Parametern deklariert, von denen der zweite optional ist. Der erste Parameter ist der aktuelle Status des Redux-Repositorys. Der zweite Parameter ist, falls übergeben, ein Objekt der Eigenschaften, die an die Komponente übergeben werden:
 const mapStateToProps = function(state) { return {   profile: state.user.profile,   loggedIn: state.auth.loggedIn } } export default connect(mapStateToProps)(ProfileComponent); 
Wenn ein reguläres Objekt von 
mapStateToProps , wird das zurückgegebene 
stateProps Objekt mit den Eigenschaften der Komponente kombiniert. Sie können in der Komponente wie folgt auf diese Eigenschaften zugreifen:
 function ProfileComponent(props) { return (   props.loggedIn     ? <Profile profile={props.profile} />     : <div>Please login to view profile.</div> ) } 
Wenn 
mapStateToProps eine Funktion zurückgibt, wird diese Funktion als 
mapStateToProps für jede Instanz der Komponente verwendet. Dies kann nützlich sein, um die Renderleistung zu verbessern und sich Notizen zu machen.
▍ mapDispatchToProps-Argument
Das Argument 
mapDispatchToProps kann entweder ein Objekt oder eine Funktion sein, die entweder ein reguläres Objekt oder eine andere Funktion zurückgibt. Um 
mapDispatchToProps besser zu veranschaulichen, benötigen wir Aktionsgeneratoren. Angenommen, wir haben die folgenden Generatoren:
 export const writeComment = (comment) => ({ comment, type: 'WRITE_COMMENT' }); export const updateComment = (id, comment) => ({ id, comment, type: 'UPDATE_COMMENT' }); export const deleteComment = (id) => ({ id, type: 'DELETE_COMMENT' }); 
Betrachten Sie nun die verschiedenen Verwendungszwecke von 
mapDispatchToProps .
Standardmäßige Standardimplementierung
Wenn Sie keine eigene 
mapDispatchToProps Implementierung verwenden, die durch ein Objekt oder eine Funktion dargestellt wird, wird eine Standardimplementierung verwendet, die die 
dispatch() Repository-Methode als Eigenschaft für die Komponente implementiert. Sie können diese Eigenschaft in einer Komponente wie der folgenden verwenden:
 import React from 'react'; import { connect } from 'react-redux'; import { updateComment, deleteComment } from './actions'; function Comment(props) { const { id, content } = props.comment; //    props.dispatch() const editComment = () => props.dispatch(updateComment(id, content)); const removeComment = () => props.dispatch(deleteComment(id)); return (   <div>     <p>{ content }</p>     <button type="button" onClick={editComment}>Edit Comment</button>     <button type="button" onClick={removeComment}>Remove Comment</button>   </div> ) } export default connect()(Comment); 
Objektübertragung
Wenn ein Objekt als Argument für 
mapDispatchToProps , wird jede Funktion im Objekt als Redux-Aktionsgenerator verwendet und in einen 
dispatch() Repository-Methodenaufruf eingeschlossen, mit dem es direkt aufgerufen werden kann. Das resultierende Objekt mit Aktionsgeneratoren, 
dispatchProps , wird mit den Eigenschaften der Komponente kombiniert.
Das folgende Beispiel zeigt ein Beispiel für die Erstellung des 
mapDispatchToProps Arguments, bei dem es sich um ein Objekt mit Aktionsgeneratoren handelt, sowie für die Verwendung von Generatoren als Eigenschaften der React-Komponente:
 import React from 'react'; import { connect } from 'react-redux'; import { updateComment, deleteComment } from './actions'; function Comment(props) { const { id, content } = props.comment; // ,   ,   const editComment = () => props.updatePostComment(id, content); const removeComment = () => props.deletePostComment(id); return (   <div>     <p>{ content }</p>     <button type="button" onClick={editComment}>Edit Comment</button>     <button type="button" onClick={removeComment}>Remove Comment</button>   </div> ) } //     const mapDispatchToProps = { updatePostComment: updateComment, deletePostComment: deleteComment } export default connect(null, mapDispatchToProps)(Comment); 
Funktionsübertragung
Wenn Sie die Funktion 
mapDispatchToProps als Argument verwenden 
mapDispatchToProps muss der Programmierer darauf achten, dass das 
dispatchProps Objekt zurückgegeben wird, das die Aktionsgeneratoren mithilfe der 
dispatch() -Speichermethode bindet. Diese Funktion akzeptiert als ersten Parameter die 
dispatch() Repository-Methode. Wie bei 
mapStateToProps kann die Funktion auch den optionalen zweiten Parameter 
ownProps , der die Zuordnung mit den ursprünglichen Eigenschaften beschreibt, die an die Komponente übergeben werden.
Wenn diese Funktion eine andere Funktion zurückgibt, wird die zurückgegebene Funktion als 
mapDispatchToProps verwendet. 
mapDispatchToProps kann hilfreich sein, um die Renderleistung und das 
mapDispatchToProps zu verbessern.
Die 
bindActionCreators() von Redux kann innerhalb dieser Funktion verwendet werden, um Aktionsgeneratoren an die Repository-Methode 
dispatch() zu binden.
Das folgende Beispiel zeigt die Verwendung einer Funktion in der Rolle von 
mapDispatchToProps . Es zeigt auch die Arbeit mit der Hilfsfunktion 
bindActionCreators() , mit der 
props.actions werden, um mit Kommentaren zu den 
props.actions der React-Komponente zu arbeiten:
 import React from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import * as commentActions from './actions'; function Comment(props) { const { id, content } = props.comment; const { updateComment, deleteComment } = props.actions; //    props.actions const editComment = () => updateComment(id, content); const removeComment = () => deleteComment(id); return (   <div>     <p>{ content }</p>     <button type="button" onClick={editComment}>Edit Comment</button>     <button type="button" onClick={removeComment}>Remove Comment</button>   </div> ) } const mapDispatchToProps = (dispatch) => { return {   actions: bindActionCreators(commentActions, dispatch) } } export default connect(null, mapDispatchToProps)(Comment); 
▍Argument mergeProps
Wenn das Argument 
mergeProps an 
connect() wird, übernimmt diese Funktion die folgenden drei Parameter:
- statePropsist das vom Aufruf- mapStateToProps()Eigenschaftsobjekt.
- dispatchProps- Ein Eigenschaftsobjekt mit Aktionsgeneratoren aus- mapDispatchToProps().
- ownProps- Die ursprünglichen Eigenschaften, die von der Komponente erhalten wurden.
Diese Funktion gibt ein einfaches Objekt mit Eigenschaften zurück, die an die umschlossene Komponente übergeben werden. Dies ist nützlich, um einen Teil des Status eines Redux-Repositorys oder eigenschaftsbasierter Aktionsgeneratoren bedingt zuzuordnen.
Wenn 
connect() diese Funktion nicht besteht, wird die Standardimplementierung verwendet:
 const mergeProps = (stateProps, dispatchProps, ownProps) => { return Object.assign({}, ownProps, stateProps, dispatchProps) } 
▍Argument, das ein Objekt mit Parametern darstellt
Ein optionales Objekt, das als viertes Argument an die Funktion 
connect() , enthält Parameter, mit denen das Verhalten dieser Funktion geändert werden kann. 
connect() ist also eine spezielle Implementierung der Funktion 
connectAdvanced() . Sie akzeptiert die meisten für 
connectAdvanced() verfügbaren Parameter sowie einige zusätzliche Parameter.
Auf der Dokumentationsseite finden Sie nach dem Lesen heraus, welche Parameter mit 
connect() können und wie sie das Verhalten dieser Funktion ändern.
Verwenden der Funktion connect ()
▍Speicher erstellen
Bevor Sie eine reguläre React-Komponente mit 
connect() in eine Containerkomponente konvertieren, müssen Sie ein Redux-Repository erstellen, mit dem diese Komponente verbunden wird.
Angenommen, wir haben eine Containerkomponente 
NewComment , mit der der Veröffentlichung neue Kommentare hinzugefügt werden. Außerdem wird eine Schaltfläche zum Senden von Kommentaren angezeigt. Der Code, der diese Komponente beschreibt, sieht möglicherweise folgendermaßen aus:
 import React from 'react'; import { connect } from 'react-redux'; class NewComment extends React.Component { input = null writeComment = evt => {   evt.preventDefault();   const comment = this.input.value;     comment && this.props.dispatch({ type: 'WRITE_COMMENT', comment }); } render() {   const { id, content } = this.props.comment;     return (     <div>       <input type="text" ref={e => this.input = e} placeholder="Write a comment" />       <button type="button" onClick={this.writeComment}>Submit Comment</button>     </div>   ) } } export default connect()(NewComment); 
Damit diese Komponente in der Anwendung verwendet werden kann, muss das Redux-Repository beschrieben werden, mit dem diese Komponente verbunden werden muss. Andernfalls tritt ein Fehler auf. Dies kann auf zwei Arten geschehen, die wir nun betrachten werden.
Festlegen der Store-Eigenschaft in einer Containerkomponente
Die erste Möglichkeit, eine Komponente mit einem Redux-Repository auszustatten, besteht darin, einen Link zu einem solchen Repository als Wert der 
store der Komponente zu übergeben:
 import React from 'react'; import store from './reduxStore'; import NewComment from './components/NewComment'; function CommentsApp(props) { return <NewComment store={store} /> } 
Festlegen der Store-Eigenschaft in der <Provider> -Komponente
Wenn Sie das Redux-Repository für die Anwendung nur einmal festlegen möchten, interessiert Sie die Methode, die wir jetzt betrachten werden. Es ist normalerweise für Anwendungen geeignet, die nur ein Redux-Repository verwenden.
Das React-Redux-Paket stellt dem Entwickler die 
<Provider> -Komponente zur Verfügung, mit der die Stammkomponente der Anwendung umbrochen werden kann. Es akzeptiert die 
store Eigenschaft. Es wird davon ausgegangen, dass es sich um eine Verknüpfung zum Redux-Repository handelt, das in der Anwendung verwendet werden soll. Die 
store Eigenschaft wird gemäß der Anwendungshierarchie mithilfe des React-Kontextmechanismus an die Containerkomponenten übergeben:
 import React from 'react'; import ReactDOM from 'react-dom'; import store from './reduxStore'; import { Provider } from 'react-redux'; import NewComment from './components/NewComment'; function CommentsApp(props) { return <NewComment /> } ReactDOM.render(( <Provider store={store}>   <CommentsApp /> </Provider> ), document.getElementById('root')) 
▍OpenProps Access Organization
Wie bereits erwähnt, können 
mapStateToProps an 
connect() mapDispatchToProps Funktionen 
mapStateToProps und 
mapDispatchToProps mit dem zweiten Parameter 
ownProps deklariert werden. 
ownProps sind die Eigenschaften der Komponente.
Es gibt jedoch ein Problem. Wenn die Anzahl der erforderlichen Parameter der deklarierten Funktion weniger als 2 
ownProps werden 
ownProps nicht übertragen. Wenn jedoch eine Funktion ohne erforderliche Parameter oder mit mindestens 2 Parametern 
ownProps wird, werden 
ownProps übergeben.
Berücksichtigen Sie verschiedene Optionen für die Arbeit mit 
ownProps .
Funktionsdeklaration ohne Parameter
 const mapStateToProps = function() { console.log(arguments[0]);  
In dieser Situation wird 
ownProps übergeben, da die Funktion ohne die erforderlichen Parameter deklariert wird. Infolgedessen funktioniert der folgende Code, der mit der neuen Syntax für die verbleibenden ES6-Parameter geschrieben wurde:
 const mapStateToProps = function(...args) { console.log(args[0]);  
Funktionsdeklaration mit einem Parameter
Betrachten Sie das folgende Beispiel:
 const mapStateToProps = function(state) { console.log(state);  
Es gibt nur einen Parameter, 
state . Infolgedessen nehmen 
arguments[1] den Wert 
undefined an, da 
ownProps nicht übertragen wird.
Funktionsdeklaration mit Standardparameter
 const mapStateToProps = function(state, ownProps = {}) { console.log(state);  
Es gibt nur einen erforderlichen Parameter, 
state , da der zweite Parameter, 
ownProps , optional ist, da er einen Standardwert hat. Da nur ein Parameter erforderlich ist, wird 
ownProps nicht übergeben, und die Zuordnung wird mit dem ihm zugewiesenen Standardwert durchgeführt, 
ownProps mit einem leeren Objekt.
Deklarieren einer Funktion mit zwei Parametern
 const mapStateToProps = function(state, ownProps) { console.log(state);  
Alles ist sehr einfach angeordnet. In einer solchen Situation wird nämlich die Übertragung von 
ownProps aufgrund der Tatsache durchgeführt, dass die Funktion mit zwei erforderlichen Parametern deklariert wird.
Zusammenfassung
Nachdem Sie dieses Material beherrscht haben, haben Sie gelernt, wann und wie Sie die 
connect() API verwenden, die vom React-Redux-Paket bereitgestellt wird und zum Erstellen von Containerkomponenten entwickelt wurde, die mit dem Redux-Status verbunden sind. Hier haben wir ausführlich über die Struktur der Funktion 
connect() und deren Arbeitsweise gesprochen. Wenn Sie jedoch mehr über diesen Mechanismus erfahren möchten, insbesondere sich mit seinen Anwendungsfällen vertraut machen möchten, lesen Sie 
diesen Abschnitt der React-Redux-Dokumentation.
Liebe Leser! Verwenden Sie React-Redux in Ihren Projekten?
