Verwenden der connect () - Funktion aus dem Paket react-redux

Ursprünglicher Autor: Glad Chinda
  • Übersetzung
In dem Artikel, dessen Übersetzung wir heute veröffentlichen, wird erläutert, wie Containerkomponenten in React-Anwendungen erstellt werden, die sich auf den Zustand von Redux beziehen. Dieses Material basiert auf der Beschreibung des Zustandskontrollmechanismus in React unter Verwendung des React -Redux-Pakets . Es wird davon ausgegangen, dass Sie bereits über grundlegende Kenntnisse der Architektur- und Bibliotheks-APIs verfügen, über die wir sprechen werden. Wenn nicht, lesen Sie die Dokumentation zu React und Redux .

Bild

Informationen zur Statusverwaltung in JavaScript-Anwendungen


React bietet dem Entwickler zwei grundlegende Mechanismen für die Übertragung von Daten an Komponenten. Dies sind Eigenschaften (Requisiten) und Status (Status). Eigenschaften sind schreibgeschützt und ermöglichen es übergeordneten Komponenten, Attribute an untergeordnete Komponenten zu übergeben. Ein Zustand ist eine lokale Entität, die in einer Komponente eingeschlossen ist und sich jederzeit während des Lebenszyklus der Komponente ändern kann.

Da state ein äußerst nützlicher Mechanismus ist, um leistungsfähige dynamische React-Anwendungen zu erstellen, ist eine ordnungsgemäße Verwaltung erforderlich. Derzeit gibt es mehrere Bibliotheken, die eine gut strukturierte Architektur für die Verwaltung des Anwendungsstatus bereitstellen. Unter ihnen - Flux , Redux , MobX .

Redux ist eine Bibliothek zum Erstellen von Containern, in denen der Status einer Anwendung gespeichert wird. Es bietet dem Entwickler klare Zustandsverwaltungstools, die sich vorhersehbar verhalten. Diese Bibliothek eignet sich für Anwendungen, die in reinem JavaScript geschrieben sind, und für Projekte, die mit einigen Frameworks entwickelt wurden. Redux ist klein, ermöglicht aber auch das Schreiben robuster Anwendungen, die in verschiedenen Umgebungen funktionieren.

So erstellen Sie Redux-Repositories:

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 Paket rea-redux stellt React-Bindungen für einen Redux-Statuscontainer bereit, wodurch das Verbinden einer React-Anwendung mit einem Redux-Repository extrem einfach ist. Auf diese Weise können Sie die Komponenten einer React-Anwendung nach ihrer Verbindung zum Repository trennen. Wir sprechen hier über folgende 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 Callbacks aufrufen, die auch über Eigenschaften an sie weitergeleitet werden.
  2. Komponentenbehälter. Sie sind für den Betrieb der internen Mechanismen der Anwendung verantwortlich und interagieren mit dem Zustand von Redux. Sie werden oft mit React-Redux erstellt, sie können Redux-Aktionen auslösen. Außerdem abonnieren sie Zustandsänderungen.

Details zu dieser Vorgehensweise bei der Aufteilung der Verantwortung der Komponenten finden Sie hier . In diesem Material werden wir hauptsächlich über Containerkomponenten sprechen, die über Reakt-Redux an den Zustand von Redux angeschlossen sind.

Das Paket rea-redux hat eine sehr einfache Schnittstelle. Das Interessanteste an dieser Schnittstelle ist das Folgende:

  1. <Provider store> - Ermöglicht das Erstellen eines Wrappers für eine React-Anwendung und den Redux-Status für alle Containerkomponenten in ihrer Hierarchie zugänglich zu machen.
  2. connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])- ermöglicht das Erstellen von Komponenten höherer Ordnung. Dies ist erforderlich, um Container-Komponenten auf Basis von React-Basiskomponenten zu erstellen.

Installieren Sie das Paket rea-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, folgt ein Beispiel für das Verbinden 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((
  <Providerstore={store}>
    <AppRootComponent />
  </Provider>
), rootElement);

Jetzt können Sie Containerkomponenten erstellen, die mit dem Redux-Repository verbunden sind. Dies geschieht innerhalb der Hierarchie AppRootComponentmithilfe der API connect().

Wann müssen Sie connect () verwenden?


▍Erstellung von Behälterkomponenten


Wie bereits erwähnt, werden mit der React-Redux-API connect()Containerkomponenten erstellt, die mit dem Redux-Repository verbunden sind. Der Speicher, zu dem die Verbindung hergestellt wird, wird vom obersten Vorfahren der Komponente mit dem Kontextmechanismus "React" abgerufen. Sie connect()benötigen die Funktion nicht, wenn Sie nur die Präsentationskomponenten erstellen.

Wenn Sie in der React-Komponente Daten aus dem Repository abrufen oder Aktionen auslösen oder beides tun müssen, können Sie eine reguläre Komponente in eine Containerkomponente konvertieren, indem Sie sie in eine übergeordnete Komponente einbetten, die von einer Funktion connect()von rea-redux zurückgegeben wird . 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 logintoview profile.</div>
  )
}
const mapStateToProps = function(state) {
  return {
    profile: state.user.profile,
    loggedIn: state.auth.loggedIn
  }
}
export defaultconnect(mapStateToProps)(ProfileContainer);

▍ Das manuelle Abonnieren des Redux-Repositorys entfällt


Sie können die Containerkomponente selbst erstellen und die Komponente mit dem Befehl manuell im Redux-Repository signieren store.subscribe(). connect()Wenn Sie die Funktion verwenden , müssen Sie jedoch einige Verbesserungen und Leistungsoptimierungen vornehmen, 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 mit dem Redux-Repository zu verbinden, um sie zu abonnieren. Hier bemühen wir uns, die gleiche Funktionalität zu implementieren, die im vorherigen Beispiel gezeigt wird.

import React, { Component } from 'react';
import store from './reduxStore';
import Profile from './components/Profile';
classProfileContainerextendsComponent{
  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;

Darüber connect()hinaus bietet die Funktion dem Entwickler zusätzliche Flexibilität, sodass Sie die Containerkomponenten anpassen können, um dynamische Eigenschaften basierend auf den ursprünglich übertragenen Eigenschaften zu erhalten. Dies ist sehr nützlich, um Samples aus einem auf Eigenschaften basierenden Zustand abzurufen oder um Aktionsgeneratoren aus Eigenschaften an eine bestimmte Variable zu binden.

Wenn Ihre React-Anwendung mehrere Redux-Repositorys verwendet, connect()können Sie auf einfache Weise das spezifische Repository angeben, mit dem die Containerkomponente verbunden werden soll.

Connect () Anatomie


Die connect()vom Paket rea-redux bereitgestellte Funktion kann bis zu vier Argumente enthalten, von denen jedes optional ist. Nach dem Aufruf der Funktion connect()wird eine übergeordnete Komponente zurückgegeben, mit der jede React-Komponente eingeschlossen werden kann.

Da die Funktion eine Komponente höherer Ordnung zurückgibt, muss sie erneut aufgerufen werden, indem die Basiskomponente React übergeben wird, um sie in eine Containerkomponente zu konvertieren:

const ContainerComponent = connect()(BaseComponent);

Hier ist die Funktionssignatur connect():

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])

MapArgument mapStateToProps


Ein Argument mapStateToPropsist eine Funktion, die entweder ein reguläres Objekt oder eine andere Funktion zurückgibt. Wird dieses Argument übergeben connect(), abonniert die Containerkomponente die Aktualisierungen des Redux-Repositorys. Dies bedeutet, dass die Funktion mapStateToPropsjedes Mal aufgerufen wird, wenn sich der Speicherstatus ändert. Wenn Sie Status - Updates sind nicht daran interessiert verfolgen, übergeben Sie connect()den Wert dieses Argument undefinedoder null.

Die Funktion wird mapStateToPropsmit zwei Parametern deklariert, von denen der zweite optional ist. Der erste Parameter repräsentiert den aktuellen Status des Redux-Repositorys. Wenn der zweite Parameter übergeben wird, handelt es sich um das Objekt der an die Komponente übergebenen Eigenschaften:

const mapStateToProps = function(state) {
  return {
    profile: state.user.profile,
    loggedIn: state.auth.loggedIn
  }
}
exportdefault connect(mapStateToProps)(ProfileComponent);

Wenn ein mapStateToPropsnormales Objekt zurückgegeben wird, wird das zurückgegebene Objekt statePropsmit den Eigenschaften der Komponente kombiniert. Sie können auf diese Eigenschaften in einer Komponente wie folgt zugreifen:

functionProfileComponent(props) {
  return (
    props.loggedIn
      ? <Profileprofile={props.profile} />
      : <div>Please login to view profile.</div>
  )
}

Wenn mapStateToPropseine Funktion zurückgegeben wird, wird diese Funktion mapStateToPropsfür jede Komponenteninstanz verwendet. Dies kann nützlich sein, um die Renderleistung zu verbessern und die Memoisierung zu verbessern.

MapArgument mapDispatchToProps


Ein Argument mapDispatchToPropskann entweder ein Objekt oder eine Funktion sein, die entweder ein reguläres Objekt oder eine andere Funktion zurückgibt. Um die Arbeit besser veranschaulichen zu können mapDispatchToProps, benötigen wir Aktionsgeneratoren. Angenommen, wir haben die folgenden Generatoren:

exportconst writeComment = (comment) => ({
  comment,
  type: 'WRITE_COMMENT'
});
exportconst updateComment = (id, comment) => ({
  id,
  comment,
  type: 'UPDATE_COMMENT'
});
exportconst deleteComment = (id) => ({
  id,
  type: 'DELETE_COMMENT'
});

Betrachten Sie nun die verschiedenen Einsatzmöglichkeiten mapDispatchToProps.

Standard-Standardimplementierung


Wenn Sie keine eigene Implementierung verwenden mapDispatchToProps, die durch ein Objekt oder eine Funktion dargestellt wird, wird die Standardimplementierung verwendet, mit der die Speichermethode dispatch()als Eigenschaft für die Komponente implementiert wird . Sie können diese Eigenschaft in der Komponente wie folgt verwenden:

import React from'react';
import { connect } from'react-redux';
import { updateComment, deleteComment } from'./actions';
functionComment(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>
      <buttontype="button"onClick={editComment}>Edit Comment</button>
      <buttontype="button"onClick={removeComment}>Remove Comment</button>
    </div>
  )
}
exportdefault connect()(Comment);

Objektübertragung


Wenn ein mapDispatchToPropsObjekt als Argument verwendet wird , wird jede Funktion im Objekt als Redux-Aktionsgenerator interpretiert und in einen Aufruf der Speichermethode eingebunden dispatch(), der den direkten Aufruf ermöglicht. Das resultierende Objekt mit den Aktionsgeneratoren dispatchPropswird mit den Eigenschaften der Komponente kombiniert.

Das folgende Beispiel zeigt ein Beispiel zum Erstellen eines Arguments mapDispatchToProps, das ein Objekt mit Aktionsgeneratoren darstellt, und wie Generatoren als Eigenschaften der React-Komponente verwendet werden können:

import React from'react';
import { connect } from'react-redux';
import { updateComment, deleteComment } from'./actions';
functionComment(props) {
  const { id, content } = props.comment;
  
  // Действия, представленные свойствами компонента, вызываются напрямую
  const editComment = () => props.updatePostComment(id, content);
  const removeComment = () => props.deletePostComment(id);
  
  return (
    <div>
      <p>{ content }</p>
      <buttontype="button"onClick={editComment}>Edit Comment</button>
      <buttontype="button"onClick={removeComment}>Remove Comment</button>
    </div>
  )
}
// Объект с генераторами действийconst mapDispatchToProps = {
  updatePostComment: updateComment,
  deletePostComment: deleteComment
}
exportdefault connect(null, mapDispatchToProps)(Comment);

Übertragungsfunktion


Wenn Sie eine mapDispatchToPropsFunktion als Argument verwenden, muss der Programmierer das Objekt dispatchProps, das die Aktionsgeneratoren mithilfe der Speichermethode bindet, unabhängig zurückgeben dispatch(). Diese Funktion akzeptiert als ersten Parameter eine Speichermethode dispatch(). Wie bei c mapStateToPropskann die Funktion auch einen optionalen zweiten Parameter annehmen ownProps, der das Mapping mit den ursprünglichen, an die Komponente übergebenen Eigenschaften beschreibt.

Wenn diese Funktion eine andere Funktion zurückgibt, wird die zurückgegebene Funktion in der Rolle verwendet. Dies mapDispatchToPropskann hilfreich sein, um die Renderleistung und das Memo zu verbessern.

HilfsfunktionbindActionCreators()Redux kann innerhalb dieser Funktion verwendet werden, um Aktionsgeneratoren an eine Speichermethode zu binden dispatch().

Das folgende Beispiel veranschaulicht die Verwendung mapDispatchToPropseiner Funktion in einer Rolle . Außerdem wird gezeigt, bindActionCreators()wie Sie mit einer Hilfsfunktion arbeiten, mit der Aktionsgeneratoren an Kommentare mit props.actionsder React-Komponente gebunden werden:

import React from'react';
import { connect } from'react-redux';
import { bindActionCreators } from'redux';
import * as commentActions from'./actions';
functionComment(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>
      <buttontype="button"onClick={editComment}>Edit Comment</button>
      <buttontype="button"onClick={removeComment}>Remove Comment</button>
    </div>
  )
}
const mapDispatchToProps = (dispatch) => {
  return {
    actions: bindActionCreators(commentActions, dispatch)
  }
}
exportdefault connect(null, mapDispatchToProps)(Comment);

▍Argument mergeProps


Wenn ein connect()Argument an die Funktion übergeben wird mergeProps, nimmt diese Funktion die folgenden drei Parameter an:

  • stateProps- Das Eigenschaftsobjekt wurde vom Anruf zurückgegeben mapStateToProps().
  • dispatchProps- Eigenschaftsobjekt mit Aktionsgeneratoren aus mapDispatchToProps().
  • ownProps - die anfänglichen Eigenschaften der Komponente.

Diese Funktion gibt ein einfaches Objekt mit Eigenschaften zurück, das an die umschlossene Komponente übergeben wird. Dies ist nützlich für die bedingte Abbildung des Status des Redux-Repository-Status oder für eigenschaftsbasierte Aktionsgeneratoren.

Wenn connect()diese Funktion nicht übergeben wird, wird ihre Standardimplementierung verwendet:

const mergeProps = (stateProps, dispatchProps, ownProps) => {
  returnObject.assign({}, ownProps, stateProps, dispatchProps)
}

▍Argument, das ein Objekt mit Parametern darstellt


Ein optionales Objekt, das connect()als viertes Argument an die Funktion übergeben wird, enthält Parameter, die das Verhalten dieser Funktion ändern sollen. Ist connect()also eine spezielle Implementierung der Funktion vorhanden connectAdvanced(), benötigt sie die meisten verfügbaren Parameter connectAdvanced()sowie einige zusätzliche Parameter.

Hier ist die Dokumentationsseite, nach deren Überprüfung Sie herausfinden können, mit welchen Parametern Sie arbeiten können connect()und wie sie das Verhalten dieser Funktion ändern.

Verwenden der connect () - Funktion


▍Erstellen Sie ein Repository


Bevor Sie eine reguläre React-Komponente mit Hilfe einer Container-Komponente konvertieren connect(), müssen Sie ein Redux-Repository erstellen, mit dem diese Komponente verbunden wird.

Angenommen, wir verfügen über eine Containerkomponente NewComment, mit der einer Publikation neue Kommentare hinzugefügt werden. Außerdem wird eine Schaltfläche zum Senden eines Kommentars angezeigt. Der Code, der diese Komponente beschreibt, könnte folgendermaßen aussehen:

importReact from 'react';
import { connect } from 'react-redux';
classNewCommentextendsReact.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}>SubmitComment</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 erfolgen, die wir jetzt betrachten werden.

Festlegen der Store-Eigenschaft in einer Containerkomponente


Die erste Möglichkeit, eine Komponente mit Redux-Speicher auszustatten, besteht darin, eine Referenz auf diesen Speicher als Wert einer storeKomponenteneigenschaft zu übergeben:

import React from'react';
import store from'./reduxStore';
import NewComment from'./components/NewComment';
functionCommentsApp(props) {
  return<NewCommentstore={store} />
}

Festlegen der Store-Eigenschaft in der <Provider> -Komponente


Wenn Sie ein Redux-Repository nur einmal für eine Anwendung einrichten möchten, interessieren Sie sich für die Methode, die wir nun betrachten werden. Es ist normalerweise für Anwendungen geeignet, die nur ein Redux-Repository verwenden.

Das Paket rea-redux stellt einem Entwickler Komponenten zur Verfügung <Provider>, mit denen die Stammkomponente einer Anwendung eingeschlossen werden kann. Es braucht Eigentum store. Es wird davon ausgegangen, dass es sich um einen Link zum Redux-Repository handelt, das in der Anwendung verwendet werden soll. Die Eigenschaft wird storegemäß der Anwendungshierarchie mit dem Kontextmechanismus "React" an 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';
functionCommentsApp(props) {
  return<NewComment />
}
ReactDOM.render((
  <Providerstore={store}>
    <CommentsApp />
  </Provider>
), document.getElementById('root'))

▍Organize Zugriff auf ownProps


Wie bereits erwähnt, können die Funktionen mapStateToPropsund mapDispatchToProps, übergeben connect(), mit dem zweiten Parameter ownProps, den Eigenschaften der Komponente , deklariert werden.
Es gibt jedoch ein Problem. Wenn die Anzahl der erforderlichen Parameter der deklarierten Funktion weniger als 2 ist, wird ownPropssie nicht übertragen. Wird die Funktion jedoch ohne die erforderlichen Parameter oder mindestens mit 2 Parametern deklariert, ownPropswird sie übertragen.

Erwägen Sie mehrere 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 es ownPropsübergeben, da die Funktion ohne die erforderlichen Parameter deklariert ist. Der folgende Code, der mit der neuen Syntax der übrigen ES6-Parameter geschrieben wurde, funktioniert daher:

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
};

Hier gibt es nur eine Option state. Als Ergebnis arguments[1]nimmt der Wert undefinedaufgrund der Tatsache an, dass er ownPropsnicht übertragen wird.

Funktionsdeklaration mit einem Standardparameter


const mapStateToProps = function(state, ownProps = {}) {
  console.log(state); // state
  console.log(ownProps); // {}
};

Es gibt hier nur einen obligatorischen Parameter, stateda der zweite Parameter ownPropsoptional ist, da er einen Standardwert hat. Da es nur einen obligatorischen Parameter gibt, wird er daher ownPropsnicht übergeben, und das Mapping wird mit dem Standardwert durchgeführt, der ihm zugewiesen wurde, d. H. Mit einem leeren Objekt.

Funktionsdeklaration mit zwei Parametern


const mapStateToProps = function(state, ownProps) {
  console.log(state); // state
  console.log(ownProps); // ownProps
};

Es ist alles sehr einfach. In einer solchen Situation wird nämlich eine Übertragung ownPropsvorgenommen, da die Funktion mit zwei obligatorischen Parametern deklariert ist.

Ergebnisse


Nachdem Sie dieses Material beherrscht haben, haben Sie erfahren, wann und wie die API verwendet wird, connect()die vom Paket react-redux bereitgestellt wird und zum Erstellen von Containerkomponenten gedacht ist, die mit dem Status Redux verbunden sind. Hier haben wir einige Details über die Gerätefunktion connect()und ihre Arbeitsweise beschrieben. Wenn Sie jedoch mehr über diesen Mechanismus erfahren möchten, um sich mit den Verwendungsmöglichkeiten vertraut zu machen, lesen Sie bitte diesen Abschnitt der Dokumentation zu react-redux.

Liebe Leserinnen und Leser! Verwenden Sie das Paket reave-redux in Ihren Projekten?


Jetzt auch beliebt: