Redux: Dokumente: Verwendung mit React Router

Erstellt am 27. Aug. 2015  ·  61Kommentare  ·  Quelle: reduxjs/redux

Die Leute haben ständig den Eindruck, dass wir React Router nicht unterstützen oder dass Sie etwas Besonderes wie redux-react-router brauchen, damit es funktioniert, oder dass es sogar erst mit React 0.14 funktioniert.

Sie können Redux mit React Router 0.13 oder 1.0 wie heute verwenden.
(Und das galt übrigens seit der ersten Veröffentlichung von Redux.)

Einige Funktionen wie Zeitreisen müssen auf Unterstützung auf RR-Seite warten, aber das ist für das Hauptproblem irrelevant. Die Leute sind verwirrt und denken, dass sie Routing heute nicht verwenden können, was einfach falsch ist.

Das in diesem Repo enthaltene reale Beispiel verwendet React Router. Alles, was Sie brauchen, ist, <Router> in <Provider> zu packen, genau wie Sie Ihre Top-Level-Komponente in eine Router-lose App packen würden.

Wenn Sie von Aktionserstellern wechseln möchten, übergeben Sie die router -Instanz als Parameter an Aktionsersteller und rufen Sie ihre Methoden auf, wenn Sie möchten. Wenn Sie den Router-Status aus dem Redux-Speicher lesen möchten, lösen Sie eine Aktion bei der Routenänderung aus und schreiben Sie einen Reducer, um damit umzugehen. Das ist es!

React-Redux-Router ist ein Experiment, bei dem versucht wird, eine natürlichere API zu entwickeln, bei der Sie einfach Aktionen senden und den Status aus dem Speicher lesen, der automatisch mit der Router-Instanz verbunden ist, aber Sie müssen ihn nicht verwenden, oder warten, bis es stabil wird! Es ist nur ein Experiment.

Wir brauchen das in Dokumenten..

docs

Hilfreichster Kommentar

Und was halten Sie davon, ein Beispiel hinzuzufügen, das zeigt, dass der React-Router universell verwendet wird?

Alle 61 Kommentare

Ich hatte das serverseitige Rendering-Beispiel ursprünglich geschrieben, um React Router in einem universellen Kontext zu verwenden. Es wurde vorgeschlagen, dass die Nutzung mit React Router ein eigenes Dokument werden könnte. Vielleicht könnten wir der Dokumentation einen Abschnitt hinzufügen?

Und was halten Sie davon, ein Beispiel hinzuzufügen, das zeigt, dass der React-Router universell verwendet wird?

Ich denke, es wäre eine gute Idee, das real-world -Beispiel so zu modifizieren, dass es universell ist. Auf diese Weise müssen Sie nichts von Grund auf neu erstellen.

Wenn Sie von Aktionserstellern wechseln möchten, übergeben Sie die Routerinstanz als Parameter an Aktionsersteller

Ich wollte nur klarstellen, dass dies nur in 0.13 funktioniert, da 1.0beta (noch?) kein createRouter -Konzept hat, richtig?

Sie können dies mit 1.0.0-beta3 aus Ihren React-Komponenten heraus tun.

class Thing extends Component {
  static contextTypes = {
    router: PropTypes.object
  }

  handleThing() {
    this.props.actionCreator(this.context.router);
  }
}

@timdorr Ist es sicher, this.context zu verwenden? Ich hatte den Eindruck, dass es nicht für die externe Verwendung gedacht war.

Ja, es ist nur undokumentiert, nicht unsicher. Es wird in 0.14 leicht geändert, aber nicht auf eine Weise, die dies brechen würde. Ich kann mir vorstellen, dass es irgendwann bald dokumentiert wird.

@timdorr Bedeutet das auch, dass es möglich ist, in 1.0.0-beta3 von einem Aktionsersteller zu einer anderen URL zu wechseln?

Ja, wenn Sie die Router-Instanz an den Aktionsersteller weitergeben, können Sie damit machen, was Sie wollen, einschließlich Übergänge.

Ich habe das zusammengewürfelt:

const loginProps = {
  handleLogin: ({email, password}) => store.dispatch(userLogin({email, password})),
};



const routes = (
  <Route path="/" handler={App}>
    <Route path="login" handler={wrapper(Login, loginProps)} />
    <Route handler={authSection}>
      <Route path="" handler={Index} />
      <Route path="users" handler={wrapper(Users, (() => store.dispatch(getUsers())))} />
      <Route path="logout" handler={wrapper(Login, (() => store.dispatch(userLogout())))} />
    </Route>
  </Route>
);

const router = createRouter({
  location: HistoryLocation,
  routes,
});

store.dispatch(receiveRouter({router}));

Warning: Failed Context Types: Required context `store` was not specified in `SmartComponent(TodoApp)`. Check the render method of `Router`.

Was kann falsch sein?

PS: RR 1.0.0-beta3

@gyzerok Stellen Sie sicher, dass Sie das gesamte () => <Router>stuff</Router> in <Provider> einpacken, genau wie es das Beispiel real-world tut.

@gaearon ja, ofc. Ich wickle es nicht in Provider ein, sondern in meine eigene Komponente, die hauptsächlich aus Copy-Paste Ihres Providers besteht. Der Unterschied besteht darin, dass ich keinen Speicher an ihn übergebe, sondern einen Speicher darin erstelle.

@gyzerok Es ist schwer zu sagen, was falsch ist, ohne den Code zu sehen. (Und reichen Sie bitte ein separates Problem ein, react-redux Repo ist ein guter Ort.)

Danke für real-wolrd Beispiel! Aber wie geht man mit AsyncProps ? Scheint, als würde die doppelte Kontextmanipulation nicht zusammenarbeiten.

import React from 'react';                                                                                                                                                                                         
import {createStore} from 'redux';                                                                                                                                                                                 
import {Provider} from 'react-redux';                                                                                                                                                                              
import {Router, Route} from 'react-router';                                                                                                                                                                        
import BrowserHistory from 'react-router/lib/BrowserHistory';                                                                                                                                                      
import AsyncProps from 'react-router/lib/experimental/AsyncProps';                                                                                                                                                 

import App from './containers/App';                                                                                                                                                                                
import reducers from './reducers';                                                                                                                                                                                 

const store = createStoreWithMiddleware(reducers);                                                                                                                                                                 
const history = new BrowserHistory();                                                                                                                                                                               

React.render(                                                                                                                                                                                                       
    <Provider store={store}>                                                                                                                                                                                        
        {() =>                                                                                                                                                                                                      
            <Router history={history} createElement={AsyncProps.createElement}>                                                                                                                                     
                <Route component={AsyncProps}>                                                                                                                                                                      
                    <Route path="/" component={App} />                                                                                                                                                              
                </Route>                                                                                                                                                                                            
            </Router>                                                                                                                                                                                               
        }                                                                                                                                                                                                           
    </Provider>,                                                                                                                                                                                                    
    document.body                                                                                                                                                                                                  
);

und App.js

import React from 'react';                                                                                                                                                                                         
import {connect} from 'react-redux';                                                                                                                                                                               

let App = React.createClass({                                                                                                                                                                                      
    statics: {                                                                                                                                                                                                     
        loadProps(params, cb) {                                                                                                                                                                                    
            // have to call this with AsyncProps                                                                                                                                                                   
        }                                                                                                                                                                                                          
    },                                                                                                                                                                                                             
    displayName: 'App',                                                                                                                                                                                            

    render() {                                                                                                                                                                                                     
        return <div children="this is app" />                                                                                                                                                                      
    }                                                                                                                                                                                                              
});                                                                                                                                                                                                                

export default connect(state => state)(App); 

Es funktioniert ohne connect Wrapper, aber es wird auch kein redux geben. Hatte jemand dieses Problem?

Oder gibt es eine andere Möglichkeit, die Navigation anzuhalten, bis die Daten geladen sind?

Statik ist eben Statik. Sie können sie auf alles setzen, einschließlich connect() Ergebnis.

let App = React.createClass({                                                                                                                                                                                      
    displayName: 'App',                                                                                                                                                                                            

    render() {                                                                                                                                                                                                     
        return <div children="this is app" />                                                                                                                                                                      
    }                                                                                                                                                                                                              
});                                                                                                                                                                                                                

App = connect(state => state)(App); 

App.loadProps = function loadProps(params, cb) {                                                                                                                                                                                    
  // have to call this with AsyncProps                                                                                                                                                                   
}                                                                                                                                                                                                          

export default App; 

@gaearon Entschuldigung, Beispiel ist nicht voll. Ich habe versucht, das Ergebnis von connect mit fehlenden statischen Requisiten zu erweitern, aber ein echtes Problem mit dem Kontext. Geben Sie mir etwas Zeit, ich werde das gesamte Beispiel in ein separates Repo verschieben

Eine andere Sache, die ich derzeit untersuche, ist das Speichern von Parametern in einem Redux-Speicher auf klare, unauffällige Weise. Nachdem ich einige Ansätze ausprobiert hatte, schrieb ich schließlich:

<Route
  component={OrderDetails}
  path='/orders/:orderId'
  onEnter={({params}) => store.dispatch(setCurrentOrder(params.orderId))} 
/>

Es ist also möglich, auf Parameter von Selektoren zu verweisen, wie unten:

export const OrderDetails = state => {
  const {order} = state;
  return {
    order: order.details.get(order.currentOrderId),
    orderId: order.currentOrderId,
    isLoading: order.isLoadingDetails,
    error: order.detailsLoadingError
  };
};

Es wird sich wahrscheinlich ändern, sobald ein weiteres stabiles react-redux-router veröffentlicht wird.

Gute Nachrichten: React Router 1.0 RC stellt jetzt die Hooks zur Verfügung, die wir brauchen.
Schau auf https://github.com/acdlite/redux-react-router vorbei und lass uns jetzt wissen, ob es dir gefällt!

@gaearon Ich habe das Problem mit react-router und experimentell AsyncProps gefunden. Das Aktualisieren des React löst das Problem

@wtfil Gut zu wissen!

Bei der Integration mit React-Router verstehe ich aus diesem Thread, dass wir die Router-Instanz an einen Aktionsersteller übergeben und Methoden darauf aufrufen können. Ich verstehe jedoch auch, dass Aktionsersteller keine Nebenwirkungen in ihrer reinsten Form haben sollen. Der einzige Fall, den ich sehe, in dem Aktionsersteller Nebenwirkungen haben dürfen, ist, wenn es sich um asynchrone Aktionen handelt, die von Middleware verarbeitet werden. Wird dann erwartet, dass Aktionsersteller, die Übergänge durchführen, eher asynchron als reine Funktionen sein sollten?

Wird dann erwartet, dass Aktionsersteller, die Übergänge durchführen, eher asynchron als reine Funktionen sein sollten?

Aktionsersteller dürfen Nebeneffekte haben. Es ist am besten, sie nach Möglichkeit zu vermeiden, aber irgendwann braucht man sie natürlich, und da Reducer rein in Redux sind und wir keinen expliziten Effektmechanismus wie in Elm haben (siehe #569 für Diskussionen), sind Aktionsersteller die Ort, um sie zu setzen.

Schauen Sie sich redux-router an. Es funktioniert auf React Router, lässt Sie jedoch Aktionen ausführen und kümmert sich um die Synchronisierung des Routers.

Warten auf React Router und Redux Router erreichen beide 1.0 ...

Ja. Wir werden ein Rezept hinzufügen, nachdem dies geschehen ist.

Also habe ich diese Diskussion verfolgt und auch ein bisschen darüber nachgedacht, wie Routing in Redux im Allgemeinen passt (siehe https://github.com/rackt/redux/issues/805). Basierend auf einigen Diskussionen in diesem Thread und einigen Experimenten habe ich einen Ansatz gefunden, den ich persönlich dem React-Router/React-Redux-Router-Glue vorziehe.

Grundsätzlich versuche ich React-Router oder Redux keine Kenntnis voneinander zu geben und sie stattdessen über eine benutzerdefinierte History-Implementierung zu verbinden. Bei diesem Ansatz wird das Routing wie folgt gehandhabt:

  1. Für route werden eine Aktion, ein Reducer und ein Schlüssel im Store erstellt.
  2. Eine standardmäßige Verlaufsimplementierung (in diesem Beispiel wird das bevorzugte createHistory verwendet, aber Sie könnten einfach createHashHistory oder was auch immer verwenden) wird erstellt und angehört. Wenn der aktuelle Standort im Browser geändert wird, wird eine ROUTE-Aktion ausgelöst, die den Standort schließlich in den Laden bringt.
  3. Eine standardmäßige React-Router-Instanz wird mit einer zweiten benutzerdefinierten Verlaufsimplementierung erstellt, die den Abonnenten (React-Router) benachrichtigt, wenn der route -Schlüssel des Geschäfts geändert wird. Es definiert auch createHref und pushState und delegiert beide an den in Schritt 2 erstellten Standardverlauf.

Das ist es. Ich denke, es bietet eine ziemlich saubere Trennung der Aufgaben zwischen Redux und React-Router und beseitigt die Notwendigkeit, eine weitere "Glue" -Bibliothek einzuziehen. Ich füge meinen Code unten ein, ich wäre sehr an Feedback interessiert:

// please pay attention to library versions, this strategy is only tested with the indicated versions
import React from 'react'; // v0.13.3
import { Provider } from 'react-redux'; // v3.1.0
import { Router, Route, IndexRoute, Link } from 'react-router'; // v1.0.0-rc3
import { createHistory } from 'history'; // v1.12.3
import { createStore } from 'redux'; // v3.0.2

// define some components
class About extends React.Component {
    render () {
        return (
            <div><h1>About</h1></div>
        )
    }
}
class Home extends React.Component {
    render () {
        return (
            <div>
                <h1>Home</h1>
                <Link to="/about">Go to about</Link>
            </div>
        )
    }
}

// create a standard history object
var history = createHistory();

// set up 'route' action and action creator
const ROUTE = 'ROUTE';
function createRouteAction (location) {
    return {
        type: ROUTE,
        payload: location
    };
}

// set up reducer. here we only define behavior for the route action
function reducer (state = {}, action) {
    if (action.type === ROUTE) {
        return Object.assign({}, state, {
            route: action.payload
        });
    }
    else {
        return state;
        // whatever other logic you need
    }
}

// create store
const store = createStore(reducer);

// this factory returns a history implementation which reads the current state
// from the redux store and delegates push state to a different history.
function createStoreHistory () {
    return {
        listen: function (callback) {
            // subscribe to the redux store. when `route` changes, notify the listener
            const unsubscribe = store.subscribe(function () {
                const route = store.getState().route;
                callback(route);
            });

            return unsubscribe;
        },
        createHref: history.createHref,
        pushState: history.pushState
    }
}

React.render(
    <Provider store={store}>
        {() =>
            <Router history={createStoreHistory()}>
                <Route path="/about" component={About} />
                <Route path="/" component={Home} />
            </Router>
        }
    </Provider>,
    document.getElementById('root') // or whatever
);

// when the url changes, dispatch a route action. this is placed at the bottom so that the first route triggers the initial render
const unlisten = history.listen(function (location) {
    store.dispatch(createRouteAction(location));
});

Ich erwähne das übrigens, weil ich denke, dass dieses Beispiel einigen Leuten wie mir helfen könnte, die mit der Verwendung von React-Router mit Redux zu kämpfen hatten, und Ihre Behauptung zu verdeutlichen, dass Redux und React-Router heute zusammen verwendet werden können.

@cappslock Ich mag es, es gibt jedoch eine Kleinigkeit. In Ihrer Implementierung ist das Ändern der Route die Aktion. Dies unterbricht den Ansatz "Aktion ist ein Ereignis, kein Befehl", was schließlich zu einigen unangenehmen Praktiken führen kann. Lassen Sie uns das Denken umkehren, möglicherweise kann jede Aktion zu einem Nebeneffekt führen, der die Adressleiste ändert (entweder eine Komponente oder die Adressleiste eines echten Browsers ....) und der Nebeneffekt führt zum Auslösen einer neuen Aktion ( ROUTE_CHANGED ). Es ist im Grunde das gleiche Muster wie das Auslösen eines API-Aufrufs.

@tomkis1 Danke für das Feedback. Wenn ich dich richtig verstehe, funktioniert das eigentlich schon so. Die Aktion ROUTE wird als Nebeneffekt der URL-Änderung ausgelöst. Vielleicht wäre ROUTE_CHANGED ein besserer Name?

Oh! Ich habe gerade nochmal nachgeschaut und du hattest Recht. Ja, ROUTE_CHANGED würde mehr Sinn machen.

Das denke ich auch. Ich würde zurückgehen und es ändern, aber dann wären diese Kommentare wirklich verwirrend :)

Der Ablauf ist zur Verdeutlichung so:

URL-Änderung -> ROUTE (oder ROUTE_CHANGED ) Aktion -> Reducer-Updates Store -> Store-Verlauf (zuvor abonniert) benachrichtigt Listener -> React-Router-Updates

Ich bevorzuge dies, weil ich nichts anderes möchte als den Store, der den vom Benutzer beobachteten Zustand der Benutzeroberfläche steuert. Es scheint auch zum Testen vorzuziehen zu sein.

Ein Nachteil dieses Ansatzes besteht darin, dass die URL als Reaktion auf die ROUTE_CHANGED -Aktion nicht aktualisiert wird. Ich bin mir nicht einmal sicher, ob dies wünschenswert ist, wenn wir sagen, dass wir nicht wollen, dass Aktionen als Befehle behandelt werden, aber ich stelle mir vor, dass es entweder als Nebeneffekt des ROUTE_CHANGED Aktionserstellers oder durch abgeschlossen werden könnte ein separater Shop-Abonnent.

Übrigens, wenn diese Diskussion den Rahmen dieses Problems sprengen sollte, lassen Sie es mich bitte wissen und ich werde es verschieben.

@cappslock Das gefällt mir sehr! Ich denke definitiv nicht, dass es ein Problem ist, dass das Versenden ROUTE_CHANGED die Route nicht ändert. Die Aktion als Ereignis und nicht als Auslöser zu behandeln, erscheint mir sauberer/verständlicher (da sie auf eine Benutzerinteraktion reagiert; Sie würden nicht erwarten, dass eine BUTTON_CLICKED -Aktion tatsächlich einen Klick auf eine Schaltfläche auslöst). Es gibt jedoch einen Teil Ihres Codes, den ich nicht verstehe. Können Sie mir diesen Teil näher erläutern?

Diese wird unten platziert, sodass die erste Route das anfängliche Rendern auslöst

@elliotdickison Danke! Ich werde versuchen, das klarzustellen, aber bitte nehmen Sie das, was ich sage, mit einem Körnchen Salz, da es eher auf Versuch und Irrtum und Annahmen als auf einer gründlichen Analyse basiert. Dies ist an dieser Stelle eher ein Proof of Concept / eine Skizze.

Als ich diesen Code über der Instanziierung von ReactRouter platziert hatte, wurde die Komponente, die der Route / entspricht, nicht gerendert. Der Router würde immer noch funktionieren, wenn Aktionen manuell abgesetzt oder der Status manuell verschoben würde, also dachte ich, es sei ein Lebenszyklusproblem mit dem Verlauf. Das Verschieben unter die Instanziierung von ReactRouter löste dieses Problem. Ich vermute, dass die Verlaufsbibliothek die Benachrichtigung über die anfängliche Route aufschiebt, bis mindestens ein Abonnent vorhanden ist. Wenn dieser Abonnent vor dem ReactRouter eingerichtet wird, erreichen ihn keine der Benachrichtigungen.

Beim Versuch, dies zu erklären, stelle ich fest, dass mein Verständnis ein wenig mangelhaft ist; Ich werde das genauer untersuchen und versuchen, eine bessere Antwort zu geben.

Ein Nachteil dieses Ansatzes besteht darin, dass die URL als Reaktion auf die Aktion ROUTE_CHANGED nicht aktualisiert wird. Ich bin mir nicht einmal sicher, ob dies wünschenswert ist, wenn wir sagen, dass wir nicht wollen, dass Aktionen als Befehle behandelt werden, aber ich stelle mir vor, dass es entweder als Nebeneffekt des ROUTE_CHANGED-Aktionserstellers oder von einem separaten Store-Abonnenten abgeschlossen werden könnte.

Ich würde sagen, dies ist erwünscht, ROUTE_CHANGED sollte auf jeden Fall von einer externen Quelle ausgelöst werden (z. B. onhashchange ...). IMO-URL-Änderungen sollten zu ROUTE_CHANGED führen, nicht umgekehrt.

Ich stimme irgendwie zu. Ich dachte, es könnte nett sein, einfach etwas zu haben, das den Store abonniert und die URL synchron hält, falls eine gesendete ROUTE_CHANGED -Aktion aus Code und nicht aus einem tatsächlichen Verlaufsereignis stammt, aber Sie könnten argumentieren, dass dieser Fall a darstellt Programmierfehler.

@cappslock dein Ansatz ist wirklich sehr gut. Könntest du einen Blogpost darüber machen?

@vojtatranta Schauen Sie sich einfach https://github.com/rackt/redux/issues/805 an. Ich denke, es war die Inspiration hinter der Implementierung.

@vojtatranta Danke! Ich habe keinen Blog, also sind so ziemlich alle Informationen, die ich habe, in diesem Thread und #805. Gibt es etwas Bestimmtes, zu dem Sie weitere Informationen wünschen?

1.0 ist raus.

Es ist Zeit zu:

  • Port-Routing-Beispiel zur Verwendung
  • Fügen Sie das Rezept „Nutzung mit Router“ basierend auf dem Beispiel real-world hinzu

:klatschen:

@gaearon können Sie auf dieses Problem verweisen, wenn das Beispiel _Verwendung mit Router_ in einer PR enthalten ist? Viele Leute, die ich kenne (mich eingeschlossen), suchen nach einer Klärung, wie diese beiden gut zusammenspielen.

Ja sicher. An diesem Punkt wird das Problem geschlossen. :-)

Vielleicht sollte jetzt redux-simple-router in Betracht gezogen werden?

redux-simple-router +1

Ich habe gerade das universelle Beispiel + React-Router (+Redux-Simple-Router) konvertiert
https://github.com/eriknyk/redux-universal-app

Hallo zusammen, was ist das Fazit dieser Diskussion? Ich sehe, dass die Dokumente nicht für die Verwendung mit React-Router aktualisiert wurden
cc @gaearon

@gaearon Nachdem ich meine Reaktionsanwendung an Redux gebunden habe, verwende ich einfach den Zustand, um die Anzeige/Ausblendung meiner Komponenten zu steuern. Daher glaube ich nicht, dass die ursprüngliche "Router" -Rolle wie RR jetzt zu meiner Anwendung passt.
Das einzige, was der "neue Router" meiner Meinung nach tun muss, ist, die URL dem Zustand (über Aktionen?) Zuzuordnen und den Zustand auch wieder der URL zuzuordnen.
Wenn wir die URL entscheiden lassen, wie die Anwendungskomponente (vielleicht einige davon) angezeigt wird, bedeutet das, dass wir zwei Zustandsquellen haben, eine ist die URL, die andere ist der Redux-Speicher, was die Sache schwieriger macht ...
Was sagen Sie dazu? sollten wir die Adressleiste einfach zu einem weiteren Bestandteil unserer Anwendung machen.

Danke

Ich verpflichte mich offiziell, dieses Dokument zu schreiben, nachdem wir https://github.com/rackt/react-router-redux/pull/259 versendet haben. Dies wird die gesegnete Art sein, React Router und Redux zu binden. In der Dokumentation zeigen wir zunächst, wie sie ohne dieses Paket verwendet werden, und führen nach und nach zwei Annehmlichkeiten ein, die das Paket bietet: Middleware und das Verschieben der Routing-Quelle der Wahrheit in den Store. Beide sind optional, daher werden wir sicherstellen, dass Sie erklären, in welchem ​​​​Fall Sie sich für deren Verwendung entscheiden möchten und was sie Ihnen gegenüber Vanilla RR bieten.

Hier ist ein Gedanke, den Sie berücksichtigen sollten: Wenn Sie irgendetwas über Middleware in Bezug auf Routing und Verlauf erklären, könnte dies auch zu einem bestimmten Teil einer realistischen Anwendung innerhalb der allgemeinen Erklärung von http://rackt.org/redux/docs/advanced/Middleware.html ( zum Beispiel in den Beispielen am Ende)

@gaearon Fortschritte bei der React Router-Dokumentation / den nächsten Schritten? Ich lese die Redux-Dokumentation durch und liebe sie, bin aber von diesen gefälschten Links enttäuscht :(

Ich habe gerade erst begonnen, die React-Router-Dokumentation in meinem persönlichen Repo neu zu schreiben, und ich plane, dort auch den Redux-Abschnitt zu haben. Vielleicht habe ich bald etwas fertig, hängt von meiner Freizeit ab. Ich halte euch auf dem Laufenden. https://github.com/knowbody/react-router-docs

Um fair zu sein, brauchen Sie nichts auf der Redux-Seite, um den React-Router zum Laufen zu bringen. Aber ja, wir müssen das tun.

Achtung: React Router 3.0 funktioniert besser mit React Redux connect() Optimierungen, und das neue withRouter() HOC bedeutet, dass Sie Kontext nicht direkt verwenden müssen.

https://twitter.com/dan_abramov/status/729768048417251328

@gaearon , @timdorr könnten Sie die Kompromisse zwischen dem Übergeben einer Routerinstanz als Argument an Aktionsersteller und dem direkten Importieren von BrowserHistory in die Aktionsersteller klären (wie hier vorgeschlagen https://github.com/reactjs/react-router/blob /master/docs/guides/NavigatingOutsideOfComponents.md?

router umschließt Ihre Verlaufsinstanz nur mit einigen Extras, aber es sind die gleichen push - und replace -Methoden zwischen den beiden Instanzen.

Danke, @timdorr.

Ich denke, dann stellt sich die Frage, warum wir die withRouter() -Komposition brauchen, wenn router im Grunde das History-Singleton umschließt (es ist ein Singleton, richtig)?

Soll es eine lockerere Kopplung zwischen einer Komponente und einer Verlaufsinstanz ermöglichen (dh verhindern, dass die Komponente direkt auf ein Singleton-Objekt zugreift)? Wenn ja, würde nicht die gleiche Logik gelten, wenn Sie von einem Aktionsersteller aus auf die Verlaufsinstanz zugreifen?

Ja, und wenn Sie Ihre eigene Verlaufsinstanz bereitstellen und kein eigenes Singleton-Modul erstellen möchten (oder können) (was verwirrend sein kann, wenn Sie mit JS-Modulsystemen nicht sehr vertraut sind). Wenn Sie das selbst tun möchten, können Sie gerne unserem Muster folgen.

Ich bin mir nicht sicher, ob es sich lohnen würde, withRouter zu dokumentieren, wie es für mehrere Komponenten höherer Ordnung verwendet werden kann. Ich versuche immer noch herauszufinden, wie ich das am besten vermeiden kann:
connect(mapStateToProps, mapDispatchToProps)(withRouter(withAnalytics(withLanguage(TestForm)))); .

Ich könnte auch so etwas wie compose verwenden?

const enhance = compose(
  connect(mapStateToProps, mapDispatchToProps),
  withRouter,
  withAnalytics,
  withLanguage
);

export default enhance(TestForm);

In meinem Anwendungsfall wird der Kontext jedoch angemeldete Benutzer, aktuelle Sprache, Themeninformationen und Analysen haben, was dies mit viel Kontext und vielen verbundenen Komponenten zu einer Herausforderung macht.

Eine andere Idee ist, die Logik withRouter und connect unter einem Kontextnamensraum zu duplizieren: withAppContext() => props.app = { user, lang, theme, analytics, router, connect? } ?

Wäre dies für die Dokumentation oder ein Beispiel für die Verwendung von withRouter mit connect Vorteil?

@gaearon gibt es dafür irgendwelche Updates, nachdem React Router 3.0.0 und deine neuen Egghead-Videos schon eine Weile draußen sind und dieser Thread seit einem Jahr geöffnet ist?

Fertig in #1929

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

cloudfroster picture cloudfroster  ·  3Kommentare

captbaritone picture captbaritone  ·  3Kommentare

vraa picture vraa  ·  3Kommentare

timdorr picture timdorr  ·  3Kommentare

vslinko picture vslinko  ·  3Kommentare