Wie Redux-Reduzierer funktionieren
Veröffentlicht: 2022-03-10state
Redux zu irgendeinem Zeitpunkt verwendet haben, sind Sie mit Sicherheit auf Reducer gestoßen. Dieses Tutorial erklärt das Konzept von Reducern und wie sie speziell in Redux funktionieren.In diesem Tutorial lernen wir das Konzept von Reducern kennen und wie sie funktionieren, insbesondere in React-Anwendungen. Um Redux zu verstehen und besser zu nutzen, ist ein solides Verständnis von Reducern unerlässlich. Reducer bieten eine Möglichkeit, den Status einer Anwendung mithilfe einer Aktion zu aktualisieren. Es ist ein integraler Bestandteil der Redux-Bibliothek.
Dieses Tutorial richtet sich an Entwickler, die mehr über Redux Reducer erfahren möchten. Ein Verständnis von React und Redux wäre von Vorteil. Am Ende des Tutorials sollten Sie die Rolle von Reducern in Redux besser verstehen. Wir werden Code-Demos und eine Anwendung schreiben, um Reducer besser zu verstehen und wie sie den Status in einer Anwendung beeinflussen.
Was ist ein Reduzierer
Ein Reducer ist eine reine Funktion, die den Zustand einer Anwendung und Aktion als Argumente nimmt und einen neuen Zustand zurückgibt. Beispielsweise kann ein Authentifizierungsreduzierer einen Anfangszustand einer Anwendung in Form eines leeren Objekts und einer Aktion annehmen, die ihm mitteilt, dass sich ein Benutzer angemeldet hat, und einen neuen Anwendungszustand mit einem angemeldeten Benutzer zurückgeben.
Reine Funktionen sind Funktionen, die keine Nebenwirkungen haben und dieselben Ergebnisse zurückgeben, wenn dieselben Argumente übergeben werden.
Unten ist ein Beispiel für eine reine Funktion:
const add = (x, y) => x + y; add(2, 5);
Das obige Beispiel gibt einen Wert zurück, der auf den Eingaben basiert. Wenn Sie 2
und 5
übergeben, erhalten Sie immer 7
, solange es sich um dieselbe Eingabe handelt, wirkt sich nichts anderes auf die Ausgabe aus, die Sie erhalten. Dies ist ein Beispiel für eine reine Funktion.
Unten sehen Sie ein Beispiel für eine Reduzierfunktion, die einen Zustand und eine Aktion annimmt.
const initialState = {}; const cartReducer = (state = initialState, action) => { // Do something here }
Lassen Sie uns die beiden Parameter definieren, die ein Reduzierer annimmt, state
und action
.
Bundesland
Ein Zustand sind die Daten, mit denen Ihre Komponente(n) arbeiten – sie enthalten die Daten, die eine Komponente benötigt, und sie bestimmen, was eine Komponente rendert. Sobald sich ein state
ändert, wird die Komponente neu gerendert. Wenn ein Anwendungsstatus von Redux verwaltet wird, ist der Reducer der Ort, an dem Statusänderungen stattfinden.
Aktion
Eine Aktion ist ein Objekt, das die Nutzlast von Informationen enthält. Sie sind die einzige Informationsquelle für den zu aktualisierenden Redux Store. Reducer aktualisieren den Speicher basierend auf dem Wert von action.type
. Hier definieren wir action.type
als ADD_TO_CART
.
Laut der offiziellen Redux-Dokumentation sind Aktionen die einzigen Dinge, die Änderungen in einer Redux-Anwendung auslösen, sie enthalten die Nutzlast für Änderungen an einem Anwendungsspeicher. Aktionen sind JavaScript-Objekte, die Redux die Art der auszuführenden Aktion mitteilen. Normalerweise werden sie als Funktionen wie die folgende definiert:
const action = { type: 'ADD_TO_CART', payload: { product: 'margarine', quantity: 4 } }
Der obige Code ist ein typischer payload
-Wert, der enthält, was ein Benutzer sendet, und der verwendet wird, um den Status der Anwendung zu aktualisieren. Wie Sie oben sehen können, enthält das Aktionsobjekt die Art der Aktion und ein Payload-Objekt, das für die Ausführung dieser bestimmten Aktion erforderlich wäre.
Aktualisieren des Zustands mit Reduzierern
Um zu zeigen, wie Reduzierer funktionieren, schauen wir uns den Zahlenzähler unten an:
const increaseAction = { type: 'INCREASE', }; const decreaseAction = { type: 'DECREASE' }; const countReducer = (state = 0, action) => { switch(action.type){ case INCREASE: return state + 1; case DECREASE : return state -1; default: return state; } };
Im obigen Code sind increaseAction
und decreaseAction
Aktionen, die im Reducer verwendet werden, um zu bestimmen, worauf der state
aktualisiert wird. Als nächstes haben wir eine Reducer-Funktion namens countReducer
, die eine action
und einen state
annimmt, dessen Wert 0
ist. Wenn der Wert von action.type
INCREASE
, geben wir einen neuen Zustand zurück, der um 1 erhöht wird, andernfalls wird bei DECREASE
ein neuer Zustand zurückgegeben, der um 1 verringert wird. In Fällen, in denen keine dieser Bedingungen gemeint ist, geben wir state
zurück.
Aktualisieren des Status mit Reduzierern: Der Spread-Operator
Der Zustand kann nicht direkt geändert werden, um den Zustand zu erstellen oder zu aktualisieren, können wir den JavaScript-Spread-Operator verwenden, um sicherzustellen, dass wir den Wert des Zustands nicht direkt ändern, sondern stattdessen ein neues Objekt zurückgeben, das einen an ihn übergebenen Zustand enthält und die Nutzlast des Benutzers.
const contactAction = { type: 'GET_CONTACT', payload: ['0801234567', '0901234567'] }; const initialState = { contacts: [], contact: {}, }; export default function (state = initialState, action) { switch (action.type) { case GET_CONTACTS: return { ...state, contacts: action.payload, }; default: return state; }
Im obigen Code verwenden wir einen Spread-Operator, um sicherzustellen, dass wir den Statuswert nicht direkt ändern. Auf diese Weise können wir ein neues Objekt zurückgeben, das mit dem übergebenen Status und der von gesendeten Nutzlast gefüllt ist Benutzer. Durch die Verwendung eines Spread-Operators können wir sicherstellen, dass der Status gleich bleibt, wenn wir alle neuen Elemente hinzufügen und auch das Kontaktfeld im Status ersetzen, falls es zuvor vorhanden war.
Redux-Reduzierer in Aktion – Eine Demo
Um Redux Reducer und ihre Funktionsweise besser zu verstehen, werden wir eine einfache Movie-Details-Finder-App implementieren, den Code und die funktionierende Version finden Sie hier auf Codesandbox. Um zu beginnen, gehen Sie zu Ihrem Terminal und initialisieren Sie eine Reaktions-App mit dem folgenden Befehl:
create-react-app movie-detail-finder
Nachdem unser Projekt initialisiert wurde, installieren wir als Nächstes die Pakete, die wir für unsere Anwendung benötigen.
npm i axios reactstrap react-redux redux redux-thunk
Sobald die Pakete installiert sind, starten wir unseren Entwicklungsserver mit dem folgenden Befehl:
npm start
Der obige Befehl sollte unseren Projektentwicklungsserver in unserem Browser starten. Als nächstes öffnen wir unser Projekt in unserem Texteditor unserer Wahl, löschen in unserem Projekt- src
-Ordner die folgenden Dateien: App.css
, App.test.js
, serviceWorker.js
und setupTests.js
. Als Nächstes löschen wir den gesamten Code, der auf die gelöschten Dateien in unserer App.js
.
Für dieses Projekt verwenden wir die Open Movie Database API, um unsere Filminformationen, Inhalte und Bilder für unsere Anwendung zu erhalten. Hier ist ein Link zur API. Sie müssen sich registrieren und Zugangsschlüssel erhalten, um sie dafür zu verwenden Wenn Sie fertig sind, fahren wir mit unserer Anwendung fort, indem wir Komponenten erstellen.
Erstellen von App-Komponenten
Erstellen Sie zuerst in unserem src
-Ordner in unserem Projektverzeichnis einen Ordner namens components und erstellen Sie innerhalb des Ordners zwei Ordner namens Movie
und Searchbar
, unsere Komponente sollte wie im Bild unten aussehen:

Building Movie-Komponente
Lassen Sie uns die Movies
-Komponente erstellen, die die Struktur der Filmdetails umreißt, die wir von unserer API erhalten. Erstellen Sie dazu im Ordner Movies
unserer Komponente eine neue Datei Movie.js
, erstellen Sie als Nächstes eine klassenbasierte Komponente für die API-Ergebnisse, machen wir das unten.
import React, { Component } from 'react'; import { Card, CardImg, CardText, CardBody, ListGroup, ListGroupItem, Badge } from 'reactstrap'; import styles from './Movie.module.css'; class Movie extends Component{ render(){ if(this.props.movie){ return ( <div className={styles.Movie}> <h3 className="text-center my-4"> Movie Name: {this.props.movie.Title} </h3> <Card className="text-primary bg-dark"> <CardImg className={styles.Img} top src={this.props.movie.Poster} alt={this.props.movie.Title}/> <CardBody> <ListGroup className="bg-dark"> <ListGroupItem> <Badge color="primary">Actors:</Badge> {this.props.movie.Actors} </ListGroupItem> <ListGroupItem> <Badge color="primary">Genre:</Badge> {this.props.movie.Genre} </ListGroupItem> <ListGroupItem> <Badge color="primary">Year:</Badge> {this.props.movie.Year} </ListGroupItem> <ListGroupItem> <Badge color="primary">Writer(s):</Badge> {this.props.movie.Writer} </ListGroupItem> <ListGroupItem> <Badge color="primary">IMDB Rating:</Badge> {this.props.movie.imdbRating}/10 </ListGroupItem> </ListGroup> <CardText className="mt-3 text-white"> <Badge color="secondary">Plot:</Badge> {this.props.movie.Plot} </CardText> </CardBody> </Card> </div> ) } return null } } export default Movie;
Im obigen Code, Verwenden von Komponenten aus dem Paket reactstrap
, können Sie die Dokumentation hier einsehen. Wir haben eine Kartenkomponente erstellt, die den Filmnamen, das Bild, das Genre, den Schauspieler, das Jahr, den Autor, die Bewertung und die Handlung enthält. Um das Übergeben von Daten von dieser Komponente zu vereinfachen, haben wir Daten als Requisiten für andere Komponenten erstellt. Als Nächstes erstellen wir unsere Searchbar
-Komponente.

Erstellen unserer Searchbar-Komponente
Unsere Searchbar
wird eine Suchleiste und eine Schaltflächenkomponente zum Durchsuchen von Filmkomponenten enthalten, lassen Sie uns dies unten tun:
import React from 'react'; import styles from './Searchbar.module.css'; import { connect } from 'react-redux'; import { fetchMovie } from '../../actions'; import Movie from '../Movie/Movie'; class Searchbar extends React.Component{ render(){ return( <div className={styles.Form}> <div> <form onSubmit={this.formHandler}> <input type="text" placeholder="Movie Title" onChange={e => this.setState({title: e.target.value})} value={this.state.title}/> <button type="submit">Search</button> </form> </div> <Movie movie={this.props.movie}/> </div> ) } }
Im obigen Code importieren wir connect
aus React react-redux
, das verwendet wird, um eine React-Komponente mit dem Redux-Speicher zu verbinden, die Komponente mit Informationen aus dem Speicher versorgt und auch Funktionen bereitstellt, die zum Senden von Aktionen an den Speicher verwendet werden. Als nächstes haben wir die Movie
Komponente und eine Funktion fetchMovie
aus Aktionen importiert.
Als nächstes haben wir ein Formular-Tag mit einem Eingabefeld für die Eingabe unserer Filmtitel. Mit dem setState
Hook von React haben wir ein onChange
-Ereignis und einen Wert hinzugefügt, der den Status des title
auf den im Eingabefeld eingegebenen Wert setzt. Wir haben ein button
-Tag, um nach Filmtiteln zu suchen, und mit der von uns importierten Movie
Komponente haben wir die Eigenschaften der Komponente als props
an das Ergebnis der Suche übergeben.
Als Nächstes müssen wir eine Funktion schreiben, um unseren Filmtitel an die API zu senden, um uns Ergebnisse zu senden. Außerdem müssen wir den Anfangsstatus der Anwendung festlegen. machen wir das unten.
class Searchbar extends React.Component{ state = { title: '' } formHandler = (event) => { event.preventDefault(); this.props.fetchMovie(this.state.title); this.setState({title: ''}); }
Hier setzen wir den Anfangszustand der Anwendung auf leere Zeichenfolgen, wir haben eine Funktion formHandler
, die einen Ereignisparameter aufnimmt und die Funktion fetchMovie
von action übergibt und den Titel als neuen Zustand der Anwendung festlegt. Um unsere Anwendung zu vervollständigen, exportieren wir diese Komponente mit der Connect-Eigenschaft von „ react-redux
“. Dazu würden wir die Eigenschaft „react redux mapToStateProps
, um den Teil der Daten auszuwählen, den unsere Komponente benötigen würde. Hier erfahren Sie mehr über mapToStateProps
.
const mapStateToProps = (state) => { return { movie: state.movie } } export default connect(mapStateToProps, { fetchMovie })(Searchbar)
Fügen wir unserem Formular Stile hinzu, indem wir eine Datei Searchbar.module.css
und die folgenden Stile hinzufügen:
.Form{ margin: 3rem auto; width: 80%; height: 100%; } input{ display: block; height: 45px; border: none; width: 100%; border-radius: 0.5rem; outline: none; padding: 0 1rem; } input:focus, select:focus{ border: 2px rgb(16, 204, 179) solid; } .Form button{ display: block; background: rgb(16, 204, 179); padding: 0.7rem; border-radius: 0.5rem; width: 20%; margin-top: 0.7rem; color: #FFF; border: none; text-decoration: none; transition: all 0.5s; } button:hover{ opacity: 0.6; } @media(max-width: 700px){ input{ height: 40px; padding: 0 1rem; } .Form button{ width: 40%; padding: 0.6rem; } }
Sobald wir das oben Gesagte getan haben, sollte unsere Suchleistenkomponente ähnlich wie das Bild unten aussehen:

Erstellen von Aktionen für die Anwendung
In dieser Komponente richten wir Redux-Aktionen für unsere Anwendung ein. Erstellen Sie zunächst im src
-Verzeichnis einen Ordner namens actions
und innerhalb des Ordners erstellen wir eine index.js
-Datei. Hier würden wir eine Funktion fetchMovie
erstellen, die einen Titelparameter aufnimmt und mithilfe von Axios einen Film von der API abruft. Lassen Sie uns dies unten tun:
import axios from 'axios'; export const fetchMovie = (title) => async (dispatch) => { const response = await axios.get( `https://cors-anywhere.herokuapp.com/https://www.omdbapi.com/?t=${title}&apikey=APIKEY`); dispatch({ type: 'FETCH_MOVIE', payload: response.data }) }
Im obigen Code haben wir Axios importiert und eine Funktion namens axios
fetchMovie
, die einen title
mithilfe von async/await übernimmt, damit wir eine Anfrage an den API-Server stellen können. Wir haben eine dispatch
-Funktion, die das Aktionsobjekt, das ihr übergeben wird, an den Redux schickt. Von dem, was wir oben haben, senden wir eine Aktion mit dem Typ FETCH_MOVIE
und der Nutzlast, die die Antwort enthält, die wir von der API erhalten haben.
HINWEIS: Der apikey in der Anfrage wird nach der Registrierung bei OmdbAPI apikey
Ihren eigenen apikey
ersetzt.
App Reducer erstellen
In diesem Abschnitt erstellen wir Reduzierstücke für unsere Anwendung.
const fetchMovieReducer = (state = null, action) => { switch(action.type){ case 'FETCH_MOVIE': return action.payload; default: return state; } } const rootReducer = (state, action) => { return { movie: fetchMovieReducer(state, action) } } export default rootReducer;
Im obigen Code haben wir einen fetchMovieReducer
erstellt, der einen Standardzustand von null
und einen action
unter Verwendung eines Switch-Operators annimmt. Für den Fall FETCH_MOVIE
wir den Wert von action.payload
zurück, bei dem es sich um den Film handelt, den wir von der API erhalten haben. Wenn sich die Aktion, die wir auszuführen versucht haben, nicht im Reducer befindet, geben wir unseren Standardzustand zurück.
Als Nächstes haben wir eine rootReducer
Funktion erstellt, die den aktuellen Status und eine Aktion als Eingabe akzeptiert und fetchMovieReducer
.
Etwas zusammensetzen
In diesem Abschnitt würden wir unsere App fertigstellen, indem wir unseren Redux-Speicher in der index.js
, machen wir das unten:
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import App from './App'; import 'bootstrap/dist/css/bootstrap.min.css'; import './index.css'; import reducers from './reducers'; const store = createStore(reducers, applyMiddleware(thunk)) ReactDOM.render( <Provider store={store}> <> <App/> </> </Provider>, document.getElementById('root') )
Im obigen Code haben wir den Anwendungsspeicher mit der store
-Methode createStore
, indem wir den von uns erstellten Reducer und eine Middleware übergeben haben. Middlewares sind Addons, die es uns ermöglichen, die Funktionalitäten von Redux zu erweitern. Hier verwenden wir die Middleware Redux Thunk mit applyMiddleware
. Die Middleware Redux Thunk ist für unseren Shop erforderlich, um asynchrone Updates durchzuführen. Dies ist erforderlich, da Redux den Speicher standardmäßig synchron aktualisiert.
Um sicherzustellen, dass unsere Anwendung den genauen zu verwendenden Speicher kennt, haben wir unsere Anwendung in eine Provider
-Komponente verpackt und den Speicher als Requisite übergeben. Auf diese Weise können andere Komponenten in unserer Anwendung eine Verbindung mit dem Speicher herstellen und Informationen mit ihm teilen.
Lassen Sie uns unserer index.css
-Datei ein wenig Stil verleihen.
*{ margin: 0; padding: 0; box-sizing: border-box; } body{ background: rgb(15, 10, 34); color: #FFF; height: 100vh; max-width: 100%; }
Rendern und Testen eines Movie Detail Finder
In diesem Abschnitt werden wir unsere Anwendung abschließen, indem wir unsere Anwendung in unserer App.js
. Dazu erstellen wir eine klassenbasierte Komponente namens App
und initialisieren unsere Suchleiste und unser Eingabefeld.
import React from 'react'; import Searchbar from './components/Searchbar/Searchbar'; import styles from './App.module.css'; class App extends React.Component{ render(){ return( <div className={styles.App}> <h1 className={styles.Title}>Movies Search App</h1> <Searchbar/> </div> ) } } export default App;
Hier haben wir eine auf der App-Klasse basierende Komponente mit einem h1
erstellt, auf dem Movie Search App steht, und unsere Searchbar
Komponente hinzugefügt. Unsere Anwendung sollte wie im folgenden Bild aussehen:

Eine funktionierende Demo ist auf Codesandbox verfügbar.
Fazit
Reducer sind ein wichtiger Bestandteil der Redux-Zustandsverwaltung. Mit Reducern können wir reine Funktionen schreiben, um bestimmte Bereiche unserer Redux-Anwendungen ohne Nebenwirkungen zu aktualisieren. Wir haben die Grundlagen von Redux-Reduzierern, ihre Verwendung und das Kernkonzept von Reduzierern, Zuständen und Argumenten gelernt.
Sie können dies weiter ausführen, indem Sie sich die Dokumentation zu Redux-Reduzierern hier ansehen. Sie können dies weiterführen und mehr auf Redux-Reduzierern aufbauen, lassen Sie mich wissen, was Sie bauen.
Ressourcen
- React-Redux-Dokumentation
- Redux-Dokumentation
-
connect()
Funktion -
applyMiddleware
Funktion