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:
stateProps
ist 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?
