Verwendung der Funktion connect () von react-redux

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 .

Bild

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:

  1. 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.
  2. 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:

  1. <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.
  2. 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 --save 

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]); // state console.log(arguments[1]); // ownProps }; 

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]); // state console.log(args[1]); // ownProps }; 

Funktionsdeklaration mit einem Parameter


Betrachten Sie das folgende Beispiel:

 const mapStateToProps = function(state) { console.log(state); // state console.log(arguments[1]); // undefined }; 

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); // state console.log(ownProps); // {} }; 

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); // state console.log(ownProps); // ownProps }; 

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?

Source: https://habr.com/ru/post/de423157/


All Articles