Ich habe gerade react-router
von v3 auf v4 ersetzt.
Ich bin mir jedoch nicht sicher, wie ich programmgesteuert in der Elementfunktion von a navigieren soll Component
. dh in der handleClick()
Funktion möchte ich /path/some/where
nach der Verarbeitung einiger Daten navigieren . Früher habe ich das gemacht durch:
import { browserHistory } from 'react-router'
browserHistory.push('/path/some/where')
Aber ich kann solche Schnittstellen in v4 nicht finden.
Wie kann ich mit v4 navigieren?
reactjs
ecmascript-6
react-router-v4
Colin Witkamp
quelle
quelle
Component
? Zum Beispiel innerhalb der Redux-Aktionen.Antworten:
Wenn Sie auf Browserumgebungen abzielen, müssen Sie
react-router-dom
stattdessen package verwendenreact-router
. Sie verfolgen den gleichen Ansatz wie React, um den Kern (react
) und den plattformspezifischen Code (react-dom
,react-native
) zu trennen , mit dem subtilen Unterschied, dass Sie nicht zwei separate Pakete installieren müssen, sodass die Umgebungspakete alles enthalten du brauchst. Sie können es Ihrem Projekt hinzufügen als:yarn add react-router-dom
oder
npm i react-router-dom
Das erste, was Sie tun müssen, ist, eine
<BrowserRouter>
übergeordnete Komponente in Ihrer Anwendung bereitzustellen .<BrowserRouter>
Verwendet die HTML5-history
API und verwaltet sie für Sie, sodass Sie sich nicht darum kümmern müssen, sie selbst zu instanziieren und<BrowserRouter>
als Requisite an die Komponente weiterzugeben (wie in früheren Versionen erforderlich).In V4 müssen Sie zum programmgesteuerten Navigieren auf das
history
über React verfügbare Objekt zugreifen ,context
sofern Sie eine<BrowserRouter>
Anbieterkomponente als oberste übergeordnete Komponente in Ihrer Anwendung haben. Die Bibliothek macht dasrouter
Objekt, das selbsthistory
eine Eigenschaft enthält, durch den Kontext verfügbar. Diehistory
Schnittstelle bietet mehrere Navigationsmethoden, wie zum Beispielpush
,replace
undgoBack
, unter anderem. Sie können die ganze Liste von Eigenschaften und Methoden überprüfen hier .Wichtiger Hinweis für Redux / Mobx-Benutzer
Wenn Sie Redux oder Mobx als Statusverwaltungsbibliothek in Ihrer Anwendung verwenden, sind möglicherweise Probleme mit Komponenten aufgetreten, die standortbezogen sein sollten, aber nach dem Auslösen einer URL-Aktualisierung nicht erneut gerendert werdenDas passiert , weil
react-router
Pässelocation
zu den Komponenten des Kontextmodells.Die 2 Lösungsansätze sind:
<Route />
. Das aktuellelocation
Objekt ist eine der Requisiten, die a<Route>
an die Komponente übergibt, die es rendertwithRouter
höherer Ordnung ein, die tatsächlich den gleichen Effekt hat undlocation
wie eine Requisite injiziertAbgesehen davon gibt es vier Möglichkeiten, programmgesteuert nach Empfehlungen zu navigieren:
1.- Verwenden einer
Es fördert einen deklarativen Stil. Vor Version 4 wurden<Route>
Komponente<Route />
Komponenten an die Spitze Ihrer Komponentenhierarchie gesetzt, wobei Sie zuvor über Ihre Routenstruktur nachdenken mussten. Jetzt können Sie jedoch<Route>
Komponenten an einer beliebigen Stelle in Ihrem Baum haben, sodass Sie je nach URL eine genauere Steuerung für das bedingte Rendern haben.Route
einspritztmatch
,location
undhistory
als Requisiten in Ihrer Komponente. Die Navigationsmethoden (wiepush
,replace
,goBack
...) werden als Eigenschaften der zur Verfügung stehendenhistory
Objekts.Es gibt 3 Möglichkeiten , etwas mit einem machen
Route
, indem man entwedercomponent
,render
oderchildren
Requisiten, aber nicht verwenden mehr als eine in den gleichenRoute
. Die Auswahl hängt vom Anwendungsfall ab, aber im Grunde werden die ersten beiden Optionen Ihre Komponente nur rendern, wenn siepath
mit dem URL-Speicherort übereinstimmt, während mitchildren
der Komponente gerendert wird, ob der Pfad mit dem Speicherort übereinstimmt oder nicht (nützlich zum Anpassen der Benutzeroberfläche basierend auf der URL passend).Wenn Sie Ihre Komponente Rendering Ausgabe anpassen möchten , müssen Sie Ihre Komponente in einer Funktion wickeln und verwenden Sie die
render
Option, um alle anderen Requisiten , um Ihre Komponente zu übergeben Sie es wünschen, abgesehen vonmatch
,location
undhistory
. Ein Beispiel zur Veranschaulichung:2.- Verwenden von
withRouter
HoCDiese Komponente höherer Ordnung injiziert die gleichen Requisiten wie
Route
. Es beinhaltet jedoch die Einschränkung, dass Sie nur 1 HoC pro Datei haben können.3.- Verwenden einer
Wenn Sie aRedirect
Komponente<Redirect>
rendern, navigieren Sie zu einem neuen Ort. Aber bedenken Sie, dass standardmäßig die aktuelle Position durch die neue ersetzt wird, wie serverseitige Umleitungen (HTTP 3xx). Der neue Speicherort wird vonto
prop bereitgestellt. Dies kann eine Zeichenfolge (URL, zu der umgeleitet werden soll) oder einlocation
Objekt sein. Wenn Sie stattdessen einen neuen Eintrag in den Verlauf verschieben möchten , übergeben Sie auch einepush
Requisite und setzen Sie sie auftrue
4.- Manueller Zugriff
Ein bisschen entmutigt, da der Kontext immer noch eine experimentelle API ist und in zukünftigen Versionen von React wahrscheinlich nicht mehr funktioniertrouter
über den KontextEs ist unnötig zu erwähnen, dass es auch andere Router-Komponenten gibt, die für Nicht-Browser-Ökosysteme gedacht sind, z. B.
<NativeRouter>
die einen Navigationsstapel im Speicher replizieren und auf die React Native-Plattform abzielen, die über dasreact-router-native
Paket verfügbar ist .Für weitere Informationen zögern Sie nicht, die offiziellen Dokumente zu lesen . Es gibt auch ein Video von einem der Co-Autoren der Bibliothek, das eine ziemlich coole Einführung in React-Router v4 bietet und einige der wichtigsten Änderungen hervorhebt.
quelle
withRouter
vonreact-router-dom
withRouter
ausreact-router-dom
. Die history.push ändert zwar die URL, scheint aber nicht zu laden,<Route>
bis ich die Seite<Router>
in einer React-Komponente habe, mit der dekoriert ist@observer
, was dieses Problem auslöst . Die Problemumgehung ist für@withRouter
jede solche React-Komponente erforderlich.withRouter
ist es einfach ein HOC, das eineRoute
unter der Haube verwendet. Das bedeutet, dass nur 3 Requisiten, Verlauf, Übereinstimmung und Ort verwendet werden . Im obigen Beispiel scheint es sichpush
um eine Requisite zu handeln,withRouter
die hinzugefügt werden würdeButtonToNavigate
, aber das ist nicht der Fall.props.history.push
müsste stattdessen verwendet werden. Hoffe das hilft anderen, die etwas verwirrt waren.browserHistory.push('/path/some/where')
scheint einfach zu viel einfacher. Die Autoren versuchen, die imperative Programmierung zu unterbinden, aber manchmal funktioniert es einfach besser!Der einfachste Weg, dies zu erreichen:
this.props.history.push("/new/url")
Hinweis:
history
prop
übergeordnete Komponente an die Komponente übergeben, für die Sie die Aktion aufrufen möchten, wenn sie nicht verfügbar ist.quelle
this.props.history
in Ihrer Komponente verfügbar sind, können Sieimport {withRouter} from 'react-router-dom'
und dannexport default withRouter(MyComponent)
(oderconst MyComponent = withRouter(...)
) und es wird dashistory
Element in die Requisiten Ihrer Komponente einfügen .history.push
und einfach ein Update auslöst, wie wenn wir auf klicken<Link>
Ich hatte ein ähnliches Problem bei der Migration auf React-Router v4, daher werde ich versuchen, meine Lösung unten zu erläutern.
Bitte betrachten Sie diese Antwort nicht als den richtigen Weg, um das Problem zu lösen. Ich kann mir vorstellen, dass eine gute Chance besteht, dass etwas Besseres entsteht, wenn React Router v4 reifer wird und die Beta verlässt (es kann sogar schon existieren und ich habe es einfach nicht entdeckt). .
Für den Kontext hatte ich dieses Problem, weil ich gelegentlich benutze
Redux-Saga
das Verlaufsobjekt programmgesteuert ändere (z. B. wenn sich ein Benutzer erfolgreich authentifiziert).Sehen Sie sich in den React Router-Dokumenten die
<Router>
Komponente an und sehen Sie, dass Sie Ihr eigenes Verlaufsobjekt über eine Requisite übergeben können. Dies ist die Essenz der Lösung - wir die Geschichte Objekt liefern , umReact-Router
von einem globalen Modul.Schritte:
yarn add history
odernpm install history --save
Erstelle eine Datei, die
history.js
in deinemApp.js
Level-Ordner aufgerufen wird (dies war meine Präferenz).Fügen Sie dieses Verlaufsobjekt wie folgt zu Ihrer Router-Komponente hinzu
Passen Sie die URL wie zuvor an, indem Sie Ihr globales Verlaufsobjekt importieren :
Alles sollte jetzt synchron bleiben, und Sie haben auch Zugriff auf eine Möglichkeit, das Verlaufsobjekt programmgesteuert und nicht über eine Komponente / einen Container festzulegen.
quelle
Route
Komponente überlieferten Requisiten verwende .TL; DR:
Die einfache und deklarative Antwort ist, dass Sie
<Redirect to={URL} push={boolean} />
in Kombination mit verwenden müssensetState()
Vollständiges Beispiel hier . Lesen Sie hier mehr .
PS. In diesem Beispiel werden ES7 + -Eigenschaftsinitialisierer verwendet, um den Status zu initialisieren. Schauen Sie auch hier , wenn Sie interessiert sind.
quelle
history.push()
Methoden verwenden.Verwenden Sie
useHistory
hook, wenn Sie Funktionskomponenten verwendenSie können
useHistory
hook verwenden, um diehistory
Instanz abzurufen.Der
useHistory
Hook gibt Ihnen Zugriff auf die Verlaufsinstanz, mit der Sie navigieren können.Verwenden Sie die
history
Eigenschaft innerhalb der SeitenkomponentenReact Router fügt einige Eigenschaften ein, einschließlich
history
Seitenkomponenten.Wickeln Sie untergeordnete Komponenten ein
withRouter
, um Routereigenschaften einzufügenwithRouter
Der Wrapper fügt den Komponenten Routereigenschaften hinzu. Mit diesem Wrapper können Sie beispielsweise den Router in die Abmeldeschaltflächenkomponente einfügen, die sich im Benutzermenü befindet.quelle
Sie können auch einfach Requisiten verwenden, um auf das Verlaufsobjekt zuzugreifen:
this.props.history.push('new_url')
quelle
this.props.history
in Ihrer Komponente verfügbar sind, können Sieimport {withRouter} from 'react-router-dom'
und dannexport default withRouter(MyComponent)
(oderconst MyComponent = withRouter(...)
) und es wird dashistory
Element in die Requisiten Ihrer Komponente einfügen .Schritt 1: Es gibt nur eine Sache, die oben importiert werden muss:
Schritt 2: Übergeben Sie auf Ihrer Route den Verlauf:
Schritt 3: Der Verlauf wird als Teil der Requisiten in der nächsten Komponente akzeptiert, sodass Sie einfach:
Das war einfach und sehr mächtig.
quelle
Das funktioniert:
quelle
Meine Antwort ähnelt der von Alex . Ich bin mir nicht sicher, warum React-Router dies so unnötig kompliziert gemacht hat. Warum sollte ich meine Komponente mit einem HoC umschließen müssen, um Zugriff auf das zu erhalten, was im Wesentlichen global ist?
Wie auch immer, wenn Sie sich ansehen, wie sie implementiert wurden
<BrowserRouter>
, ist es nur ein winziger Wrapper um die Geschichte .Wir können diesen Verlauf herausziehen, damit wir ihn von überall importieren können. Der Trick besteht jedoch darin, dass beim serverseitigen Rendern und beim Versuch,
import
das Verlaufsmodul zu verwenden, dies nicht funktioniert, da nur Browser-APIs verwendet werden. Dies ist jedoch in Ordnung, da wir normalerweise nur als Reaktion auf einen Klick oder ein anderes clientseitiges Ereignis umleiten. Daher ist es wahrscheinlich in Ordnung, es zu fälschen:Mithilfe von Webpack können wir einige Variablen definieren, damit wir wissen, in welcher Umgebung wir uns befinden:
Und jetzt kannst du
Von überall. Es wird nur ein leeres Modul auf dem Server zurückgegeben.
Wenn Sie diese magischen Variablen nicht verwenden möchten, müssen Sie sich nur
require
in dem globalen Objekt befinden, in dem sie benötigt werden (in Ihrem Ereignishandler).import
funktioniert nicht, weil es nur auf der obersten Ebene funktioniert.quelle
Ich denke, dass @rgommezz die meisten Fälle abdeckt, abzüglich eines, den ich für ziemlich wichtig halte.
Auf diese Weise kann ich einen einfachen Dienst mit Aktionen / Aufrufen schreiben, die ich aufrufen kann, um die Navigation von jeder gewünschten Komponente aus durchzuführen, ohne viel HoC für meine Komponenten auszuführen ...
Es ist nicht klar, warum noch niemand diese Lösung bereitgestellt hat. Ich hoffe, es hilft, und wenn Sie ein Problem damit sehen, lassen Sie es mich bitte wissen.
quelle
Ich habe v4 jetzt seit ein paar Tagen getestet und .. Ich liebe es bis jetzt! Es macht nur nach einer Weile Sinn.
Ich hatte auch die gleiche Frage und fand, dass der Umgang damit wie folgt am besten funktioniert (und möglicherweise sogar so ist, wie es beabsichtigt ist). Es verwendet state, einen ternären Operator und
<Redirect>
.Im Konstruktor ()
Im Render ()
Im Clickhandler ()
Ich hoffe es hilft. Gib mir Bescheid.
quelle
Ich hatte eine Weile damit zu kämpfen - etwas so Einfaches und doch so Kompliziertes, weil ReactJS nur eine völlig andere Art ist, Webanwendungen zu schreiben, es ist uns älteren Leuten sehr fremd!
Ich habe eine separate Komponente erstellt, um das Durcheinander zu abstrahieren:
Fügen Sie es dann Ihrer
render()
Methode hinzu:quelle
Da es keinen anderen Weg gibt, mit diesem schrecklichen Design umzugehen, habe ich eine generische Komponente geschrieben, die den
withRouter
HOC- Ansatz verwendet. Das folgende Beispiel umschließt einbutton
Element, Sie können jedoch zu jedem anklickbaren Element wechseln, das Sie benötigen:Verwendungszweck:
quelle
Wenn Sie this.props.history in Ihrer Komponente nicht verfügbar gefunden haben, versuchen Sie dies
quelle
Da ich manchmal lieber die Routen nach Anwendung als nach Schaltflächen wechsle, ist dies ein minimales Arbeitsbeispiel, das für mich funktioniert:
quelle
Für diejenigen unter Ihnen, die eine Umleitung benötigen, bevor sie einen Router mit
React Router
oder vollständig umleitenReact Router Dom
können. Sie können eine Umleitung bereitstellen, indem Sie einfach auf das Verlaufsobjekt zugreifen und einen neuen Status in Ihrem Konstruktor von darauf verschiebenapp.js
. Folgendes berücksichtigen:Hier möchten wir die Ausgaberouten abhängig von einer Subdomain ändern, indem wir mit dem Verlaufsobjekt interagieren, bevor die Komponente gerendert wird. Wir können effektiv umleiten, während unsere Routen weiterhin intakt bleiben.
quelle