von Michael Sargent

Eine Routing-Bibliothek ist eine Schlüsselkomponente jeder komplexen, einseitigen Anwendung. Wenn Sie Web-Apps mit React und Redux entwickeln, haben Sie wahrscheinlich React Router verwendet oder zumindest davon gehört. Es ist eine bekannte Routing-Bibliothek für React und eine großartige Lösung für viele Anwendungsfälle.

Aber React Router ist nicht die einzige praktikable Lösung im React / Redux-Ökosystem. Tatsächlich gibt es unzählige Routing-Lösungen für React und Redux mit jeweils unterschiedlichen APIs, Funktionen und Zielen — und die Liste wächst weiter. Unnötig zu erwähnen, dass das clientseitige Routing nicht so schnell verschwindet und in den Routing-Bibliotheken von morgen noch viel Platz für das Design bleibt.

Heute möchte ich Sie auf das Thema Routing in Redux aufmerksam machen. Ich werde Redux-first Routing vorstellen und argumentieren — ein Paradigma, das Redux zum Star des Routing-Modells und zum roten Faden vieler Redux-Routing-Lösungen macht. Ich zeige Ihnen, wie Sie die Framework-agnostische Kern-API in weniger als 100 Codezeilen zusammenstellen, bevor Sie Optionen für die reale Verwendung mit React und anderen Front-End-Frameworks untersuchen.

Eine kleine Geschichte

Im Browser werden der Standort (URL-Informationen) und der Sitzungsverlauf (ein Stapel von Standorten, die vom aktuellen Browser-Tab besucht werden) im globalen window -Objekt gespeichert. Sie sind erreichbar über:

  • window.location ( Standort API)
  • window.history ( Geschichte API).

Die History-API bietet die folgenden Verlaufsnavigationsmethoden, die sich durch ihre Fähigkeit auszeichnen, den Verlauf und den Speicherort des Browsers zu aktualisieren, ohne dass eine Seite neu geladen werden muss:

  • pushState(href) — schiebt einen neuen Speicherort in den Verlaufsstapel
  • replaceState(href) — überschreibt die aktuelle Position auf dem Stapel
  • back() — navigiert zur vorherigen Position auf dem Stapel
  • forward() — navigiert zur nächsten Position auf dem Stapel
  • go(index) — navigiert in beide Richtungen zu einer Position auf dem Stapel.

Zusammen ermöglichen die History- und Location-APIs das moderne clientseitige Routing-Paradigma, das als pushState Routing bekannt ist – der erste Protagonist unserer Geschichte.

Nun ist es fast ein Verbrechen, die History- und Location-APIs zu erwähnen, ohne eine moderne Wrapper-Bibliothek wie history zu erwähnen.

ReactTraining/history
Sitzungsverlauf verwalten mit JavaScriptgithub.com

history bietet eine einfache, aber leistungsstarke API für die Schnittstelle mit dem Browserverlauf und dem Speicherort, während Inkonsistenzen zwischen verschiedenen Browserimplementierungen abgedeckt werden. Es wird als Peer oder interne Abhängigkeit in vielen modernen Routing-Bibliotheken verwendet, und ich werde in diesem Artikel mehrere Verweise darauf machen.

Redux und pushState Routing

Der zweite Protagonist unserer Geschichte ist Redux. Es ist 2017, also erspare ich Ihnen die Einführung und komme gleich auf den Punkt:

Durch die Verwendung von einfachem pushState-Routing in einer Redux-Anwendung teilen wir den Anwendungsstatus auf zwei Domänen auf: den Browserverlauf und den Redux-Speicher.

So sieht das mit React Router aus, der instanziiert und umschließt history:

history → React Router ↘ view Redux ↗

Nun wissen wir, dass sich nicht alle Daten im Speicher befinden müssen. Beispielsweise ist der lokale Komponentenstatus häufig ein geeigneter Ort zum Speichern von Daten, die für eine einzelne Komponente spezifisch sind.

Aber Standortdaten sind nicht trivial. Es ist ein dynamischer und wichtiger Teil des Anwendungsstatus – die Art von Daten, die in den Speicher gehören. Das Halten im Geschäft ermöglicht Redux-Luxus wie Zeitreise-Debugging und einfachen Zugriff von jeder mit dem Geschäft verbundenen Komponente.

Wie verschieben wir also den Standort in den Laden?

Es gibt keinen Weg um die Tatsache, dass der Browser liest und speichert Geschichte und Standortinformationen in der window, aber was wir tun können, ist eine Kopie der Standortdaten im Speicher zu halten, und halten Sie es synchron mit dem Browser.

Ist es nicht das, was react-router-redux für den Router tut?

Ja, aber nur, um die Zeitreisefunktionen der Redux DevTools zu aktivieren. Die Anwendung hängt weiterhin von den im Router gespeicherten Standortdaten ab:

history → React Router ↘ ↕ view Redux ↗

Es wird davon abgeraten, react-router-redux zum Lesen von Standortdaten aus dem Store anstelle des Routers zu verwenden (aufgrund potenziell widersprüchlicher Wahrheitsquellen).

Können wir es besser machen?

Können wir ein alternatives Routing—Modell erstellen — eines, das von Grund auf so aufgebaut ist, dass es gut mit Redux spielt und es uns ermöglicht, den Standort auf Redux-Weise zu lesen und zu aktualisieren – mit store.getState() und store.dispatch()?

Wir können es absolut, und es heißt Redux-first Routing.

Redux-Erstes Routing

Redux-first Routing ist eine Variation des pushState Routings, die Redux zum Star des Routingmodells macht.

Eine Redux-first Routing-Lösung erfüllt die folgenden Kriterien:

  • Der Standort befindet sich im Redux Store.
  • Der Speicherort wird durch das Versenden von Redux-Aktionen geändert.
  • Die Anwendung liest Standortdaten ausschließlich aus dem Speicher.
  • Der Store und der Browserverlauf werden hinter den Kulissen synchron gehalten.

Hier ist eine Grundidee, wie das aussieht:

history ↕ Redux → router → view

Moment, gibt es nicht noch zwei Quellen für Standortdaten?

Ja, aber wenn wir darauf vertrauen können, dass der Browserverlauf und der Redux-Speicher synchron sind, können wir unsere Anwendungen so erstellen, dass sie immer nur Standortdaten aus dem Speicher lesen. Dann gibt es aus Sicht der Anwendung nur eine Quelle der Wahrheit — den Laden.

Wie erreichen wir Redux-first Routing?

Wir können mit der Erstellung eines konzeptionellen Modells beginnen, indem wir die grundlegenden Elemente der clientseitigen Routing- und Redux-Datenlebenszyklusmodelle zusammenführen.

Überprüfung des clientseitigen Routingmodells

Das clientseitige Routing ist ein mehrstufiger Prozess, der mit der Navigation beginnt und mit dem Rendern endet — das Routing selbst ist nur ein Schritt in diesem Prozess! Lassen Sie uns die Details überprüfen:

  • Navigation – Alles beginnt mit einem Ortswechsel. Es gibt 2 Arten der Navigation: interne und externe. Die interne Navigation erfolgt aus der App heraus (z. b. über die History-API), während die externe Navigation erfolgt, wenn der Benutzer mit der Navigationsleiste des Browsers interagiert oder die Anwendung von einer externen Site aus aufruft.
  • Auf Navigation reagieren – Wenn sich der Standort ändert, antwortet die Anwendung, indem sie den neuen Standort an den Router weiterleitet. Ältere Routing-Techniken verließen sich auf Polling window.location, um dies zu erreichen, aber heutzutage haben wir das praktische Dienstprogramm history.listen.
  • Routing – Als nächstes wird der neue Speicherort mit dem entsprechenden Seiteninhalt abgeglichen. Der Code, der diesen Schritt handhabt, wird als Router bezeichnet und benötigt im Allgemeinen einen Eingabeparameter für übereinstimmende Routen und Seiten, der als Routenkonfiguration bezeichnet wird.
  • Rendern – Schließlich wird der Inhalt auf dem Client gerendert. Dieser Schritt kann natürlich von einem Front-End-Framework / einer Front-End-Bibliothek wie React ausgeführt werden.

Beachten Sie, dass Routingbibliotheken nicht jeden Teil des Routingmodells verarbeiten müssen.

Einige Bibliotheken, wie React Router und Vue Router, tun dies — während andere, wie Universal Router, sich nur mit einem einzigen Aspekt (wie Routing) befassen und somit Flexibilität in den anderen Aspekten bieten:

Routingbibliotheken können unterschiedliche Verantwortungsbereiche haben. (Zum Vergrößern anklicken)

Überarbeitung des Redux-Datenlebenszyklusmodells

Redux verfügt über ein Einweg-Datenfluss- / Lebenszyklusmodell, das wahrscheinlich keiner Einführung bedarf – aber hier ist ein kurzer Überblick für eine gute Maßnahme:

  • Aktion – Jede Statusänderung beginnt mit dem Senden einer Redux-Aktion (ein einfaches Objekt, das eine type und optionale Nutzlast enthält).
  • Middleware – Die Aktion durchläuft die Middlewarekette des Geschäfts, in der Aktionen abgefangen und zusätzliches Verhalten ausgeführt werden können. Middlewares werden häufig verwendet, um Nebenwirkungen in Redux-Anwendungen zu behandeln.
  • Reducer – Die Aktion erreicht dann den Root-Reducer, der den nächsten Zustand des Speichers als reine Funktion des vorherigen Zustands und der empfangenen Aktion berechnet. Der Wurzelreduzierer kann aus einzelnen Reduzierern bestehen, die jeweils einen Ausschnitt des Speicherzustands behandeln.
  • Neuer Status – Der Store speichert den vom Reducer zurückgegebenen neuen Status und benachrichtigt seine Abonnenten über die Änderung (in React über connect ).
  • Rendern – Schließlich kann die mit dem Speicher verbundene Ansicht gemäß dem neuen Status neu gerendert werden.

Erstellen eines Redux-First-Routingmodells

Die unidirektionale Natur der clientseitigen Routing- und Redux-Datenlebenszyklusmodelle eignet sich gut für ein zusammengeführtes Modell, das die Kriterien erfüllt, die wir für das Redux-First-Routing festgelegt haben.

In diesem Modell ist der Router im Store abonniert, die Navigation erfolgt über Redux-Aktionen und Aktualisierungen des Browserverlaufs werden von einer benutzerdefinierten Middleware verwaltet. Lassen Sie uns die Details dieses Modells untersuchen:

  • Interne Navigation über Redux-Aktionen – Anstatt die History-API direkt zu verwenden, wird die interne Navigation durch Senden einer von 5 Navigationsaktionen erreicht, die die History-Navigationsmethoden widerspiegeln.
  • Aktualisieren des Browserverlaufs über Middleware – Eine Middleware wird verwendet, um die Navigationsaktionen abzufangen und den Nebeneffekt der Aktualisierung des Browserverlaufs zu behandeln. Da der neue Speicherort nicht unbedingt oder leicht bekannt ist, ohne vorher den Browserverlauf zu konsultieren (z. im Falle einer go -Aktion) wird verhindert, dass die Navigationsaktionen den Reduzierer erreichen.
  • Reagieren auf Navigation – Der Ausführungsfluss wird mit einem history Listener fortgesetzt, der auf die Navigation (sowohl von der Middleware als auch von der externen Navigation) reagiert, indem er eine zweite Aktion ausführt, die den neuen Speicherort enthält.
  • Location Reducer – Die vom Listener ausgelöste Aktion erreicht dann den location Reducer, der den Standort zum Store hinzufügt. Der Standortreduzierer bestimmt auch die Form des Standortzustands.
  • Verbundenes Routing – Der mit dem Geschäft verbundene Router kann dann reaktiv den neuen Seiteninhalt bestimmen, wenn er über eine Änderung des Standorts im Geschäft informiert wird.
  • Rendern – Schließlich kann die Seite mit dem neuen Inhalt neu gerendert werden.

Beachten Sie, dass dies nicht der einzige Weg ist, Redux-first Routing zu erreichen — einige Variationen beinhalten die Verwendung eines Store Enhancers und / oder zusätzlicher Logik in der Middleware — aber es ist ein einfaches Modell, das alle Grundlagen abdeckt.

Eine grundlegende Implementierung

Lassen Sie uns nach dem gerade betrachteten Modell die Kern—API implementieren – Aktionen, Middleware, Listener und Reducer.

Wir verwenden das Paket history als interne Abhängigkeit und erstellen die Lösung schrittweise. Wenn Sie das Endergebnis lieber verfolgen möchten, können Sie es hier anzeigen.

Aktionen

Wir beginnen mit der Definition der 5 Navigationsaktionen, die die Verlaufsnavigationsmethoden widerspiegeln:

// constants.jsexport const PUSH = 'ROUTER/PUSH';export const REPLACE = 'ROUTER/REPLACE';export const GO = 'ROUTER/GO';export const GO_BACK = 'ROUTER/GO_BACK';export const GO_FORWARD = 'ROUTER/GO_FORWARD';
// actions.jsexport const push = (href) => ({ type: PUSH, payload: href,});
export const replace = (href) => ({ type: REPLACE, payload: href,});
export const go = (index) => ({ type: GO, payload: index,});
export const goBack = () => ({ type: GO_BACK,});
export const goForward = () => ({ type: GO_FORWARD,});

Middleware

Als nächstes definieren wir die Middleware. Es sollte die Navigationsaktionen abfangen, die entsprechenden history -Navigationsmethoden aufrufen und dann verhindern, dass die Aktion den Reduzierer erreicht — aber alle anderen Aktionen ungestört lassen:

// middleware.jsexport const routerMiddleware = (history) => () => (next) => (action) => { switch (action.type) { case PUSH: history.push(action.payload); break; case REPLACE: history.replace(action.payload); break; case GO: history.go(action.payload); break; case GO_BACK: history.goBack(); break; case GO_FORWARD: history.goForward(); break; default: return next(action); }};

Wenn Sie noch keine Gelegenheit hatten, die Interna einer Redux-Middleware zu schreiben oder zu untersuchen, lesen Sie diese Einführung.

History Listener

Als nächstes benötigen wir einen history Listener, der auf die Navigation reagiert, indem er eine neue Aktion mit den neuen Standortinformationen auslöst.

Zuerst fügen wir den neuen Aktionstyp und Ersteller hinzu. Die interessanten Teile des Standorts sind pathname, search und hash – das werden wir also in die Nutzlast aufnehmen:

// constants.jsexport const LOCATION_CHANGE = 'ROUTER/LOCATION_CHANGE';
// actions.jsexport const locationChange = ({ pathname, search, hash }) => ({ type: LOCATION_CHANGE, payload: { pathname, search, hash, },});

Dann schreiben wir die Listener-Funktion:

// listener.jsexport function startListener(history, store) { history.listen((location) => { store.dispatch(locationChange({ pathname: location.pathname, search: location.search, hash: location.hash, })); });}

Wir werden einen kleinen Zusatz machen – einen anfänglichen locationChange -Versand, um den ersten Eintrag in die Anwendung zu berücksichtigen (der vom Verlaufslistener nicht erfasst wird):

// listener.jsexport function startListener(history, store) { store.dispatch(locationChange({ pathname: history.location.pathname, search: history.location.search, hash: history.location.hash, }));
 history.listen((location) => { store.dispatch(locationChange({ pathname: location.pathname, search: location.search, hash: location.hash, })); });}

Reducer

Als nächstes definieren wir den location Reducer. Wir verwenden eine einfache Zustandsform und führen minimale Arbeit im Reduzierer aus:

// reducer.jsconst initialState = { pathname: '/', search: '', hash: '',};
export const routerReducer = (state = initialState, action) => { switch (action.type) { case LOCATION_CHANGE: return { ...state, ...action.payload, }; default: return state; }};

Anwendungscode

Lassen Sie uns schließlich unsere API in den Anwendungscode einbinden:

// index.jsimport { combineReducers, applyMiddleware, createStore } from 'redux'import { createBrowserHistory } from 'history'import { routerReducer } from './reducer'import { routerMiddleware } from './middleware'import { startListener } from './listener'import { push } from './actions'
// Create the history objectconst history = createBrowserHistory()
// Build the root reducerconst rootReducer = combineReducers({ // ...otherReducers, router: routerReducer,}) // Build the middlewareconst middleware = routerMiddleware(history)
// Create the storeconst store = createStore(rootReducer, {}, applyMiddleware(middleware))
// Start the history listenerstartListener(history, store)
// Now you can read location data from the store!let currentLocation = store.getState().router.pathname
// You can also subscribe to changes in the location!let unsubscribe = store.subscribe(() => { let previousLocation = currentLocation currentLocation = store.getState().router.pathname
 if (previousLocation !== currentLocation) { // You can render your application reactively here! }})
// And you can dispatch navigation actions from anywhere!store.dispatch(push('/about'))

Und das ist alles, was es dazu gibt! Mit unserer winzigen API (unter 100 Codezeilen) haben wir alle Kriterien für Redux-first Routing erfüllt:

  • Der Standort befindet sich im Redux Store. ✔
  • Der Speicherort wird durch Senden von Redux-Aktionen geändert. ✔
  • Die Anwendung liest Standortdaten ausschließlich aus dem Geschäft. ✔
  • Der Store und der Browserverlauf werden hinter den Kulissen synchron gehalten. ✔

Sehen Sie sich hier alle Dateien zusammen an — importieren Sie sie in Ihr Projekt oder verwenden Sie sie als Ausgangspunkt für die Entwicklung Ihrer eigenen Implementierung.

Das Redux-first-Routing-Paket

Ich habe die API auch in das redux-first-routing -Paket eingefügt, das Sie npm install und auf die gleiche Weise verwenden können.

mksarge /redux-first-routing
redux-first-routing – Eine minimale, framework-agnostische Basis für die Durchführung von Redux-First-Routing.github.com

Es enthält eine ähnliche Implementierung wie die, die wir hier erstellt haben, jedoch mit dem bemerkenswerten Zusatz der Abfrageanalyse über das Paket query-string.

Warte – was ist mit der eigentlichen Routing-Komponente?

Sie haben vielleicht bemerkt, dass redux-first-routing sich nur mit dem Navigationsaspekt des Routingmodells befasst:

Durch die Entkopplung des Navigationsaspekts von den anderen Aspekten unseres Routingmodells haben wir eine gewisse Flexibilität gewonnen — redux-first-routing ist sowohl router- als auch Framework-unabhängig.

Sie können es daher mit einer Bibliothek wie Universal Router koppeln, um eine vollständige Redux-First-Routing-Lösung für jedes Front-End-Framework zu erstellen:

Klicken Sie hier, um mit redux-first-routing + universal-router zu beginnen.

Oder Sie könnten meinungsbildende Bindungen für Ihr Framework Ihrer Wahl erstellen – und das werden wir im nächsten und letzten Abschnitt dieses Artikels für React tun.

Verwendung mit React

Beenden wir unsere Untersuchung, indem wir uns ansehen, wie wir speicherverbundene Komponenten für die deklarative Navigation und das Routing in React erstellen können.

Deklarative Navigation

Für die Navigation können wir eine mit dem Speicher verbundene <Link/> -Komponente verwenden, die der in React Router und anderen React Routing-Lösungen ähnelt.

Es überschreibt einfach das Standardverhalten des Ankerelements <a/> und dispatches eine Push-Aktion, wenn Sie darauf klicken:

// Link.jsimport React from 'react';import { connect } from 'react-redux';import { push as pushAction, replace as replaceAction } from './actions';
const Link = (props) => { const { to, replace, children, dispatch, ...other } = props;
 const handleClick = (event) => { // Ignore any click other than a left click if ((event.button && event.button !== 0) || event.metaKey || event.altKey || event.ctrlKey || event.shiftKey || event.defaultPrevented === true) { return; } // Prevent the default behaviour (page reload, etc.) event.preventDefault();

 // Dispatch the appropriate navigation action if (replace) { dispatch(replaceAction(to)); } else { dispatch(pushAction(to)); } };
 return ( <a href={to} onClick={handleClick} {...other}> {children} </a>);};
export default connect()(Link);

Eine vollständigere Implementierung finden Sie hier.

Deklaratives Routing

Obwohl eine Navigationskomponente nicht viel zu bieten hat, gibt es unzählige Möglichkeiten, eine Routingkomponente zu entwerfen — was sie zum interessantesten Teil jeder Routinglösung macht.

Was ist eigentlich ein Router?

Sie können einen Router im Allgemeinen als Funktion oder Blackbox mit zwei Eingängen und einem Ausgang betrachten:

route configuration ↘ matched content current location ↗

Obwohl das Routing und das anschließende Rendern in separaten Schritten erfolgen können, macht es React einfach und intuitiv, sie in einer deklarativen Routing-API zu bündeln. Schauen wir uns zwei Strategien an, um dies zu erreichen.

Strategie 1: Eine monolithische <Router/> Komponente

Wir können eine monolithische, mit dem Speicher verbundene <Router/> Komponente verwenden, die:

  • akzeptiert ein Routenkonfigurationsobjekt über Requisiten
  • liest die Standortdaten aus dem Redux-Speicher
  • berechnet den neuen Inhalt, wenn sich der Standort ändert
  • rendert / rendert den Inhalt entsprechend.

Die Routenkonfiguration kann ein einfaches JavaScript-Objekt sein, das alle übereinstimmenden Pfade und Seiten enthält (eine zentralisierte Routenkonfiguration).

So könnte das aussehen:

const routes = 
React.render( <Provider store={store}> <Router routes={routes}> </Provider>, document.getElementById('app'))

Ziemlich einfach, oder? Es sind keine verschachtelten JSX-Routen erforderlich – nur ein einzelnes Routenkonfigurationsobjekt und eine einzelne Routerkomponente.

Wenn Ihnen diese Strategie gefällt, lesen Sie meine vollständigere Implementierung in der redux-json-router -Bibliothek. Es umschließt redux-first-routing und bietet React-Bindungen für deklarative Navigation und Routing mit den bisher untersuchten Strategien.

mksarge / redux-json-router
redux-json-router – Deklaratives, Redux-erstes Routing für React / Redux-Browser applications.github.com

Strategie 2: Composable <Route/> components

Während eine monolithische Komponente eine einfache Möglichkeit sein kann, deklaratives Routing in React zu erreichen, ist dies definitiv nicht die einzige Möglichkeit.

Die Zusammensetzbarkeit von React ermöglicht eine weitere interessante Möglichkeit: mit JSX Routen dezentral zu definieren. Das Paradebeispiel ist natürlich die <Route/> -API von React Router:

React.render( <BrowserRouter> <Route path='/' component={Home}/> <Route path='/about component={About}/> ... </BrowserRouter>

Andere Routing-Bibliotheken untersuchen diese Idee ebenfalls. Obwohl ich keine Gelegenheit dazu hatte, sehe ich keinen Grund, warum eine ähnliche API nicht über dem Paket redux-first-routing implementiert werden konnte.

Anstatt sich auf Standortdaten zu verlassen, die von <BrowserRoute r / >, the &l t;Route / > Komponente could si mply Verbindung zum Speicher herstellen:

React.render( <Provider store={store}> <Route path='/' component={Home}/> <Route path='/about component={About}/> ... </Provider>

Wenn Sie daran interessiert sind, dies zu erstellen oder zu verwenden, lassen Sie es mich in den Kommentaren wissen! Um mehr über verschiedene Routenkonfigurationsstrategien zu erfahren, lesen Sie diese Einführung auf der Website des Routers.

Fazit

Ich hoffe, diese Untersuchung hat dazu beigetragen, Ihr Wissen über clientseitiges Routing zu vertiefen und Ihnen gezeigt, wie einfach es ist, dies auf Redux-Weise zu erreichen.

Wenn Sie nach einer vollständigen Redux-Routing-Lösung suchen, können Sie das redux-first-routing -Paket mit einem kompatiblen Router verwenden, der in der Readme-Datei aufgeführt ist. Und wenn Sie eine maßgeschneiderte Lösung entwickeln müssen, hat Ihnen dieser Beitrag hoffentlich einen guten Ausgangspunkt dafür gegeben.

Wenn Sie mehr über clientseitiges Routing in React und Redux erfahren möchten, lesen Sie die folgenden Artikel – sie haben mir geholfen, die hier behandelten Themen besser zu verstehen:

  • Lassen Sie die URL von Tyler Thompson sprechen
  • Möglicherweise benötigen Sie keinen Router von Konstantin Tarkus
  • Brauche ich überhaupt eine Routing-Bibliothek? von James K. Nelson
  • und unzählige informative Diskussionen in den react-router-redux Ausgaben.

Client-Side-Routing ist ein Raum mit endlosen Gestaltungsmöglichkeiten, und ich bin sicher, dass einige von Ihnen mit Ideen gespielt haben, die denen ähneln, die ich hier geteilt habe. Wenn Sie das Gespräch fortsetzen möchten, werde ich mich freuen, mit Ihnen in den Kommentaren oder über Twitter zu verbinden. Danke fürs Lesen!

Bearbeiten 22/06/17: Lesen Sie auch diesen Artikel über redux-first-router, ein separates Projekt, das intelligente Aktionstypen verwendet, um leistungsstarke Routingfunktionen zu erreichen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.