Wie kann ich in React Router v4 zum Verlauf wechseln?


360

In der aktuellen Version von React Router (v3) kann ich eine Serverantwort akzeptieren und verwenden browserHistory.push, um zur entsprechenden Antwortseite zu gelangen. Dies ist jedoch in Version 4 nicht verfügbar, und ich bin mir nicht sicher, wie ich damit umgehen soll.

In diesem Beispiel ruft components / app-product-form.js unter Verwendung von Redux auf, this.props.addProduct(props)wenn ein Benutzer das Formular sendet . Wenn der Server einen Erfolg zurückgibt, wird der Benutzer zur Warenkorbseite weitergeleitet.

// actions/index.js
export function addProduct(props) {
  return dispatch =>
    axios.post(`${ROOT_URL}/cart`, props, config)
      .then(response => {
        dispatch({ type: types.AUTH_USER });
        localStorage.setItem('token', response.data.token);
        browserHistory.push('/cart'); // no longer in React Router V4
      });
}

Wie kann ich von der Funktion für React Router v4 eine Umleitung zur Warenkorbseite vornehmen?


Nur um dies aus der zuletzt angebotenen Lösung und aus Vorschlägen in den Problemen von React Router auf GitHub hinzuzufügen, contextist es ein "no go" , das zu verwenden , um das zu übergeben, was Sie manuell benötigen. Sofern ich kein Bibliotheksautor bin, sollte es nicht erforderlich sein, es zu verwenden. In der Tat empfiehlt Facebook dagegen.
Chris

@ Chris hast du eine Lösung dafür gefunden? Ich muss auf eine andere Komponente in Aktion drängen, wie Sie hier erklärt haben
Mr.G

@ Mr.G, leider habe ich nicht. Zuletzt habe ich gelesen, dass das React Training-Team, das den React Router verwaltet, ein Redux-Paket zur Verfügung hat. Ich hatte kein Glück, dass es funktioniert, und sie haben nicht viel Arbeit in die Lösung gesteckt.
Chris

Warum können wir windows.location.href = URL nicht verwenden? Ist etwas falsch daran, die URL zu ändern und umzuleiten?
Shan

Ich verstehe nicht, warum nicht, aber die Option zur Verwendung historyfunktioniert auch für React Native als Option sowie als zusätzliche Option zur Unterstützung älterer Browser.
Chris

Antworten:


308

Sie können die historyMethoden außerhalb Ihrer Komponenten verwenden. Versuchen Sie es auf folgende Weise.

Erstellen Sie zunächst ein historyObjekt, das im Verlaufspaket verwendet wird :

// src/history.js

import { createBrowserHistory } from 'history';

export default createBrowserHistory();

Wickeln Sie es dann ein <Router>( bitte beachten Sie, dass Sie es import { Router }anstelle von verwenden sollten import { BrowserRouter as Router }):

// src/index.jsx

// ...
import { Router, Route, Link } from 'react-router-dom';
import history from './history';

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <div>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/login">Login</Link></li>
        </ul>
        <Route exact path="/" component={HomePage} />
        <Route path="/login" component={LoginPage} />
      </div>
    </Router>
  </Provider>,
  document.getElementById('root'),
);

Ändern Sie Ihren aktuellen Standort von einem beliebigen Ort aus, zum Beispiel:

// src/actions/userActionCreators.js

// ...
import history from '../history';

export function login(credentials) {
  return function (dispatch) {
    return loginRemotely(credentials)
      .then((response) => {
        // ...
        history.push('/');
      });
  };
}

UPD : Sie können auch ein etwas anderes Beispiel in den häufig gestellten Fragen zu React Router sehen .


24
Ich habe versucht, genau das zu tun, was @OlegBelostotsky gesagt hat, aber danach history.push('some path')ändert sich die URL, aber die Seite ändert sich nicht. Ich muss window.location.reload()einige Teile meines Codes danach einfügen, damit es funktioniert. In einem Fall muss ich jedoch den Redux-Statusbaum behalten, und das erneute Laden zerstört ihn. Irgendeine andere Lösung?
Sdabrutas

2
@idunno Versuchen Sie, die withRouterKomponente höherer Ordnung zu verwenden.
Oleg Belostotsky

Dies warf mir einen Fehler mit der Angabe: createBrowserHistory ist keine Funktion. Was kann ich machen?
AKJ

@AKJ Vielleicht import createHistory from 'history/createBrowserHistory'; export default createHistory();wird Arbeit sein.
Oleg Belostotsky

1
Entschuldigung für die Ablehnung :). Während dies auch funktionieren sollte, antwortete Chris wie folgt : stackoverflow.com/a/42716055/491075 .
gion_13

340

React Router v4 unterscheidet sich grundlegend von v3 (und früheren Versionen) und Sie können nicht mehr so ​​tun, browserHistory.push()wie Sie es früher getan haben .

Diese Diskussion scheint verwandt zu sein, wenn Sie weitere Informationen wünschen:

  • Das Erstellen einer neuen Instanz browserHistoryfunktioniert nicht, da <BrowserRouter>eine eigene Verlaufsinstanz erstellt wird und Änderungen daran abgehört werden. Eine andere Instanz ändert also die URL, aktualisiert sie jedoch nicht <BrowserRouter>.
  • browserHistory wird in v4 nicht vom React-Router verfügbar gemacht, sondern nur in v2.

Stattdessen haben Sie einige Möglichkeiten, dies zu tun:

  • Verwenden Sie die withRouterKomponente höherer Ordnung

    Stattdessen sollten Sie die withRouterKomponente höherer Ordnung verwenden und diese in die Komponente einschließen, die in den Verlauf verschoben wird. Zum Beispiel:

    import React from "react";
    import { withRouter } from "react-router-dom";
    
    class MyComponent extends React.Component {
      ...
      myFunction() {
        this.props.history.push("/some/Path");
      }
      ...
    }
    export default withRouter(MyComponent);

    Weitere Informationen finden Sie in der offiziellen Dokumentation :

    Sie können den Zugriff auf das bekommen historyEigenschaften des Objekts und die nächste <Route>‚s matchüber die withRouter höhere Ordnung Komponente. withRouter rendert seine Komponente jedes Mal neu, wenn sich die Route mit denselben Requisiten ändert wie <Route>Render-Requisiten : { match, location, history }.


  • Verwenden Sie die contextAPI

    Die Verwendung des Kontexts ist möglicherweise eine der einfachsten Lösungen, aber als experimentelle API ist sie instabil und wird nicht unterstützt. Verwenden Sie es nur, wenn alles andere fehlschlägt. Hier ist ein Beispiel:

    import React from "react";
    import PropTypes from "prop-types";
    
    class MyComponent extends React.Component {
      static contextTypes = {
        router: PropTypes.object
      }
      constructor(props, context) {
         super(props, context);
      }
      ...
      myFunction() {
        this.context.router.history.push("/some/Path");
      }
      ...
    }

    Schauen Sie sich die offizielle Dokumentation zum Kontext an:

    Wenn Sie möchten, dass Ihre Anwendung stabil ist, verwenden Sie keinen Kontext. Es ist eine experimentelle API und wird wahrscheinlich in zukünftigen Versionen von React kaputt gehen.

    Wenn Sie trotz dieser Warnungen darauf bestehen, Kontext zu verwenden, versuchen Sie, die Verwendung von Kontext auf einen kleinen Bereich zu beschränken, und vermeiden Sie es, die Kontext-API nach Möglichkeit direkt zu verwenden, damit ein Upgrade bei Änderungen der API einfacher ist.


9
Ja, ich habe es versucht. Danke für die Frage. :-) Wie bekommt man den Kontext in diese Aktionsfunktion? Bisher ist es undefiniert.
Chris

1
Ich habe dieses Thema seit einigen Tagen erforscht und konnte es nicht zum Laufen bringen. Selbst wenn ich das obige Beispiel verwende, bekomme ich immer wieder Router, die im Kontext nicht definiert sind. Ich verwende derzeit react v15.5.10, react-router-dom v4.1.1, prop-types 15.5.10. Die Dokumentation dazu ist spärlich und nicht sehr klar.
Stu

5
@Stu das sollte funktionierenthis.context.router.history.push('/path');
Tushar Khatiwada

1
@Chris Wenn Sie versuchen, ein Verlaufsobjekt zu instanziieren und es selbst zu verwenden, wird die URL geändert, die Komponente wird jedoch nicht gerendert - wie oben erwähnt. Aber wie kann man "history.push" auch außerhalb der Komponente verwenden und das Rendern von Komponenten erzwingen?
cool

52
Dies beantwortet nicht die gestellte Frage, wie auf history.push AUSSERHALB einer Komponente zugegriffen werden soll. Die Verwendung von withRouter oder des Kontexts ist keine Option, wenn Sie sich außerhalb einer Komponente befinden.
SunshinyDoyle

49

Mit React-Router v5 können Sie jetzt den useHistory-Lifecycle-Hook wie folgt verwenden:

import { useHistory } from "react-router-dom";

function HomeButton() {
  let history = useHistory();

  function handleClick() {
    history.push("/home");
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}

Lesen Sie mehr unter: https://reacttraining.com/react-router/web/api/Hooks/usehistory


1
Das ist ein sehr willkommenes Update! Vielen Dank!
Chris

Gibt es eine bestimmte Art und Weise, wie ich dies einrichten muss ? Ich rufe Folgendes auf let history = useHistory();, Object is not callableerhalte jedoch eine Fehlermeldung, als ich versuchte zu sehen, welche VerwendungHistorie console.log(useHistory)als undefiniert angezeigt wird . using"react-router-dom": "^5.0.1"
steff_bdh

@steff_bdh Sie müssen es in Ihrer Datei package.json auf "react-router-dom": "^ 5.0.1" aktualisieren und 'npm install' ausführen
Hadi Abu

2
Schön, aber ich kann keinen Hook in Redux-Aktionsklassen verwenden, da sie keine Komponente / Funktion reagieren
Jay

Wie würden Sie dies für die Umleitung bei der Anmeldung mit (async) verwenden? Hier ist die Frage => stackoverflow.com/questions/62154408/…
theairbend3r

29

Der einfachste Weg in React Router 4 ist die Verwendung

this.props.history.push('/new/url');

Um diese Methode verwenden zu können, sollte Ihre vorhandene Komponente Zugriff auf das historyObjekt haben. Wir können Zugang bekommen durch

  1. Wenn Ihre Komponente Routedirekt mit verknüpft ist , hat Ihre Komponente bereits Zugriff auf das historyObjekt.

    z.B:

    <Route path="/profile" component={ViewProfile}/>

    Hier ViewProfilehat Zugang zu history.

  2. Wenn nicht Routedirekt verbunden.

    z.B:

    <Route path="/users" render={() => <ViewUsers/>}

    Dann müssen wir withRoutereine Funktion höherer Ordnung verwenden, um die vorhandene Komponente zu verziehen.

    Innerhalb ViewUsers Komponente

    • import { withRouter } from 'react-router-dom';

    • export default withRouter(ViewUsers);

    Das war's jetzt, Ihre ViewUsersKomponente hat Zugriff auf das historyObjekt.

AKTUALISIEREN

2- Übergeben Sie in diesem Szenario alle Routen propsan Ihre Komponente, und dann können wir this.props.historyvon der Komponente aus auch ohne eine zugreifenHOC

z.B:

<Route path="/users" render={props => <ViewUsers {...props} />}

1
Ausgezeichnet! Ihre zweite Methode hat auch den Trick für mich getan, da meine Komponente (auf die zugegriffen werden muss this.props.history) von einem HOC stammt, was bedeutet, dass sie nicht direkt mit dem verknüpft ist Route, wie Sie erklären.
Cjauvin

25

So habe ich es gemacht:

import React, {Component} from 'react';

export default class Link extends Component {
    constructor(props) {
        super(props);
        this.onLogout = this.onLogout.bind(this);
    }
    onLogout() {
        this.props.history.push('/');
    }
    render() {
        return (
            <div>
                <h1>Your Links</h1>
                <button onClick={this.onLogout}>Logout</button>
            </div>
        );
    }
}

Verwenden this.props.history.push('/cart'); diese Option, um zur Warenkorbseite umzuleiten, die im Verlaufsobjekt gespeichert wird.

Viel Spaß, Michael.


2
Ja, es sieht so aus, als könnten Sie innerhalb der Komponenten ganz gut pushen. Die einzige Möglichkeit, die Navigation außerhalb einer Komponente zu beeinflussen, ist die Umleitung.
Chris

14
Dies beantwortet nicht die gestellte Frage, wie auf history.push AUSSERHALB einer Komponente zugegriffen werden soll. Die Verwendung von this.props.history ist keine Option, wenn Sie sich außerhalb einer Komponente befinden.
SunshinyDoyle

22

Gemäß der Dokumentation zu React Router v4 - Redux Deep Integration-Sitzung

Eine tiefe Integration ist erforderlich, um:

"durch Auslösen von Aktionen navigieren können"

Sie empfehlen diesen Ansatz jedoch als Alternative zur "tiefen Integration":

"Anstatt Aktionen zur Navigation auszulösen, können Sie das bereitgestellte Verlaufsobjekt übergeben, um Komponenten an Ihre Aktionen weiterzuleiten und dort damit zu navigieren."

So können Sie Ihre Komponente mit der withRouter-Komponente höherer Ordnung umschließen:

export default withRouter(connect(null, { actionCreatorName })(ReactComponent));

Dadurch wird die Verlaufs-API an Requisiten übergeben. Sie können also den Aktionsersteller aufrufen, der den Verlauf als Parameter übergibt. Zum Beispiel in Ihrer ReactComponent:

onClick={() => {
  this.props.actionCreatorName(
    this.props.history,
    otherParams
  );
}}

Dann in Ihren Aktionen / index.js:

export function actionCreatorName(history, param) {
  return dispatch => {
    dispatch({
      type: SOME_ACTION,
      payload: param.data
    });
    history.push("/path");
  };
}

19

Die böse Frage hat mich ziemlich viel Zeit gekostet, aber schließlich habe ich sie folgendermaßen gelöst:

Wickeln Sie Ihren Container mit ein withRouterund übergeben Sie den Verlauf an Ihre mapDispatchToPropsfunktionierende Aktion . Verwenden Sie in Aktion history.push ('/ url'), um zu navigieren.

Aktion:

export function saveData(history, data) {
  fetch.post('/save', data)
     .then((response) => {
       ...
       history.push('/url');
     })
};

Container:

import { withRouter } from 'react-router-dom';
...
const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    save: (data) => dispatch(saveData(ownProps.history, data))}
};
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Container));

Dies gilt für Router v4.x Reagieren .


Vielen Dank, Ihre withRouter-Lösung funktioniert mit Typoskript, ist aber im Vergleich zu früher ziemlich langsam import { createBrowserHistory } from 'history' .
Jay

7

this.context.history.push wird nicht funktionieren.

Ich habe es geschafft, Push so zum Laufen zu bringen:

static contextTypes = {
    router: PropTypes.object
}

handleSubmit(e) {
    e.preventDefault();

    if (this.props.auth.success) {
        this.context.router.history.push("/some/Path")
    }

}

9
Dies beantwortet nicht die gestellte Frage, wie auf history.push AUSSERHALB einer Komponente zugegriffen werden soll. Die Verwendung von this.context ist keine Option, wenn Sie sich außerhalb einer Komponente befinden.
SunshinyDoyle

6

In diesem Fall geben Sie Requisiten an Ihren Thunk weiter. Sie können also einfach anrufen

props.history.push('/cart')

Ist dies nicht der Fall, können Sie den Verlauf Ihrer Komponente trotzdem übergeben

export function addProduct(data, history) {
  return dispatch => {
    axios.post('/url', data).then((response) => {
      dispatch({ type: types.AUTH_USER })
      history.push('/cart')
    })
  }
}

6

Ich biete eine weitere Lösung an, falls es sich für jemand anderen lohnt.

Ich habe eine history.jsDatei, in der ich Folgendes habe:

import createHistory from 'history/createBrowserHistory'
const history = createHistory()
history.pushLater = (...args) => setImmediate(() => history.push(...args))
export default history

Als nächstes verwende ich auf meinem Root, wo ich meinen Router definiere, Folgendes:

import history from '../history'
import { Provider } from 'react-redux'
import { Router, Route, Switch } from 'react-router-dom'

export default class Root extends React.Component {
  render() {
    return (
     <Provider store={store}>
      <Router history={history}>
       <Switch>
        ...
       </Switch>
      </Router>
     </Provider>
    )
   }
  }

Schließlich actions.jsimportiere ich auf meinem Verlauf den Verlauf und benutze pushLater

import history from './history'
export const login = createAction(
...
history.pushLater({ pathname: PATH_REDIRECT_LOGIN })
...)

Auf diese Weise kann ich nach API-Aufrufen neue Aktionen ausführen.

Ich hoffe es hilft!


4

Wenn Sie Redux verwenden, würde ich empfehlen, das npm-Paket react-router-redux zu verwenden . Sie können damit Redux-Store-Navigationsaktionen auslösen.

Sie müssen den Speicher wie in der Readme-Datei beschrieben erstellen .

Der einfachste Anwendungsfall:

import { push } from 'react-router-redux'

this.props.dispatch(push('/second page'));

Zweiter Anwendungsfall mit Container / Komponente:

Container:

import { connect } from 'react-redux';
import { push } from 'react-router-redux';

import Form from '../components/Form';

const mapDispatchToProps = dispatch => ({
  changeUrl: url => dispatch(push(url)),
});

export default connect(null, mapDispatchToProps)(Form);

Komponente:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class Form extends Component {
  handleClick = () => {
    this.props.changeUrl('/secondPage');
  };

  render() {
    return (
      <div>
        <button onClick={this.handleClick}/>
      </div>Readme file
    );
  }
}

1
Dies funktioniert nicht mit React-Router-Redux, es sei denn, Sie verwenden die nextVersion, die sich derzeit noch in der Entwicklung befindet!
Froginvasion

4

Dies konnte ich mit erreichen bind(). Ich wollte auf eine Schaltfläche klicken index.jsx, einige Daten auf dem Server veröffentlichen, die Antwort auswerten und zu umleiten success.jsx. So habe ich das herausgefunden ...

index.jsx::

import React, { Component } from "react"
import { postData } from "../../scripts/request"

class Main extends Component {
    constructor(props) {
        super(props)
        this.handleClick = this.handleClick.bind(this)
        this.postData = postData.bind(this)
    }

    handleClick() {
        const data = {
            "first_name": "Test",
            "last_name": "Guy",
            "email": "test@test.com"
        }

        this.postData("person", data)
    }

    render() {
        return (
            <div className="Main">
                <button onClick={this.handleClick}>Test Post</button>
            </div>
        )
    }
}

export default Main

request.js::

import { post } from "./fetch"

export const postData = function(url, data) {
    // post is a fetch() in another script...
    post(url, data)
        .then((result) => {
            if (result.status === "ok") {
                this.props.history.push("/success")
            }
        })
}

success.jsx::

import React from "react"

const Success = () => {
    return (
        <div className="Success">
            Hey cool, got it.
        </div>
    )
}

export default Success

So durch Bindung thisan postDatain index.jsx, ich war in der Lage , den Zugang this.props.historyin request.js... dann kann ich diese Funktion wieder verwenden in verschiedenen Komponenten, so stellen müssen , dass ich mich erinnere enthalten this.postData = postData.bind(this)in der constructor().


3

Hier ist mein Hack (dies ist meine Root-Level-Datei mit einem kleinen Redux - obwohl ich sie nicht benutze react-router-redux):

const store = configureStore()
const customHistory = createBrowserHistory({
  basename: config.urlBasename || ''
})

ReactDOM.render(
  <Provider store={store}>
    <Router history={customHistory}>
      <Route component={({history}) => {
        window.appHistory = history
        return (
          <App />
        )
      }}/>
    </Router>
  </Provider>,
  document.getElementById('root')
)

Ich kann dann window.appHistory.push()überall verwenden, wo ich möchte (zum Beispiel in meinen Redux-Store-Funktionen / Thunks / Sagas usw.). Ich hatte gehofft, ich könnte es nur verwenden, window.customHistory.push()aber aus irgendeinem Grund react-routerschien es nie zu aktualisieren, obwohl sich die URL geändert hat. Aber auf diese Weise habe ich die EXACT-Instanz react-routerverwendet. Ich mag es nicht, Dinge in den globalen Bereich zu stellen, und dies ist eines der wenigen Dinge, mit denen ich das machen würde. Aber es ist besser als jede andere Alternative, die ich IMO gesehen habe.


3

Rückruf verwenden. Es hat bei mir funktioniert!

export function addProduct(props, callback) {
  return dispatch =>
    axios.post(`${ROOT_URL}/cart`, props, config)
    .then(response => {
    dispatch({ type: types.AUTH_USER });
    localStorage.setItem('token', response.data.token);
    callback();
  });
}

In der Komponente müssen Sie nur den Rückruf hinzufügen

this.props.addProduct(props, () => this.props.history.push('/cart'))

3

So mache ich das: - Anstatt mit umzuleiten history.push, verwende ich nur die RedirectKomponente von. react-router-dom Wenn Sie diese Komponente verwenden, können Sie sie einfach übergeben push=true, und sie kümmert sich um den Rest

import * as React from 'react';
import { Redirect } from 'react-router-dom';
class Example extends React.Component {
  componentDidMount() {
    this.setState({
      redirectTo: '/test/path'
    });
  }

  render() {
    const { redirectTo } = this.state;

    return <Redirect to={{pathname: redirectTo}} push={true}/>
  }
}

Dies ist die richtige, die nicht reagieren Render-Zyklus zu brechen
jzqa

1

Mit React Router V4 kann die Verlaufs-Requisite jetzt wie folgt verwendet werden:

this.props.history.push("/dummy",value)

Auf den Wert kann dann überall dort zugegriffen werden, wo die Standortstütze als state:{value}Nicht-Komponentenstatus verfügbar ist .


1
Dies beantwortet nicht die gestellte Frage, wie auf history.push AUSSERHALB einer Komponente zugegriffen werden soll. Die Verwendung von this.props.history ist keine Option, wenn Sie sich außerhalb einer Komponente befinden.
Arkady

0

Sie können es so verwenden, wie ich es für Login und Manny verschiedene Dinge mache

class Login extends Component {
  constructor(props){
    super(props);
    this.login=this.login.bind(this)
  }


  login(){
this.props.history.push('/dashboard');
  }


render() {

    return (

   <div>
    <button onClick={this.login}>login</login>
    </div>

)

0
/*Step 1*/
myFunction(){  this.props.history.push("/home"); }
/**/
 <button onClick={()=>this.myFunction()} className={'btn btn-primary'}>Go 
 Home</button>

Keine Importe nötig!
David Bagdasaryan

1
Während dieser Code die Frage möglicherweise beantwortet, verbessert die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie dieser Code die Frage beantwortet, ihren langfristigen Wert.
Rollstuhlfahrer

0

Schritt eins Wickeln Sie Ihre App in Router

import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));

Jetzt hat meine gesamte App Zugriff auf BrowserRouter. Schritt zwei Ich importiere Route und gebe diese Requisiten weiter. Wahrscheinlich in einer Ihrer Hauptdateien.

import { Route } from "react-router-dom";

//lots of code here

//somewhere in my render function

    <Route
      exact
      path="/" //put what your file path is here
      render={props => (
      <div>
        <NameOfComponent
          {...props} //this will pass down your match, history, location objects
        />
      </div>
      )}
    />

Wenn ich jetzt console.log (this.props) in meiner js-Komponentendatei ausführe, sollte ich etwas bekommen, das so aussieht

{match: {…}, location: {…}, history: {…}, //other stuff }

Schritt 2 Ich kann auf das Verlaufsobjekt zugreifen, um meinen Standort zu ändern

//lots of code here relating to my whatever request I just ran delete, put so on

this.props.history.push("/") // then put in whatever url you want to go to

Außerdem bin ich nur ein Bootcamp-Student für Codierung, daher bin ich kein Experte, aber ich weiß, dass Sie auch Sie verwenden können

window.location = "/" //wherever you want to go

Korrigieren Sie mich, wenn ich falsch liege, aber als ich das getestet habe, wurde die gesamte Seite neu geladen, was meiner Meinung nach den gesamten Sinn der Verwendung von React zunichte gemacht hat.


0

Erstellen Sie eine benutzerdefinierte Routermit seiner eigenen browserHistory:

import React from 'react';
import { Router } from 'react-router-dom';
import { createBrowserHistory } from 'history';

export const history = createBrowserHistory();

const ExtBrowserRouter = ({children}) => (
  <Router history={history} >
  { children }
  </Router>
);

export default ExtBrowserRouter

RouterVerwenden Sie als Nächstes auf Ihrer Wurzel, auf der Sie Ihre definieren , Folgendes:

import React from 'react';       
import { /*BrowserRouter,*/ Route, Switch, Redirect } from 'react-router-dom';

//Use 'ExtBrowserRouter' instead of 'BrowserRouter'
import ExtBrowserRouter from './ExtBrowserRouter'; 
...

export default class Root extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <ExtBrowserRouter>
          <Switch>
            ...
            <Route path="/login" component={Login}  />
            ...
          </Switch>
        </ExtBrowserRouter>
      </Provider>
    )
  }
}

Importieren historySie schließlich, wo Sie es benötigen, und verwenden Sie es:

import { history } from '../routers/ExtBrowserRouter';
...

export function logout(){
  clearTokens();      
  history.push('/login'); //WORKS AS EXPECTED!
  return Promise.reject('Refresh token has expired');
}

0

Wenn Sie den Verlauf verwenden möchten, während Sie eine Funktion als Wert an die Requisite einer Komponente übergeben, können Sie mit React-Router 4 die historyRequisite einfach im Render-Attribut der <Route/>Komponente zerstören und dann verwendenhistory.push()

    <Route path='/create' render={({history}) => (
      <YourComponent
        YourProp={() => {
          this.YourClassMethod()
          history.push('/')
        }}>
      </YourComponent>
    )} />

Hinweis: Damit dies funktioniert, sollten Sie die BrowserRouter-Komponente von React Router um Ihre Stammkomponente wickeln (z. B. in index.js).

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.