React-Router gehen eine Seite zurück Wie konfigurieren Sie den Verlauf?


121

Kann mir bitte jemand sagen, wie ich zur vorherigen Seite zurückkehren kann, anstatt zu einer bestimmten Route?

Bei Verwendung dieses Codes:

var BackButton = React.createClass({

 mixins: [Router.Navigation],
  render: function() {
    return (
        <button
            className="button icon-left"
            onClick={this.navigateBack}>
            Back
        </button>
    );
  },

  navigateBack: function(){
    this.goBack();
  }
});

Erhalten Sie diesen Fehler, goBack () ignoriert, da kein Routerverlauf vorhanden ist

Hier sind meine Routen:

// Routing Components
Route = Router.Route;
RouteHandler = Router.RouteHandler;
DefaultRoute = Router.DefaultRoute;

var routes = (
 <Route name="app" path="/" handler={OurSchoolsApp}>
     <DefaultRoute name="home" handler={HomePage} />
     <Route name="add-school" handler={AddSchoolPage}  />
     <Route name="calendar" handler={CalendarPage}  />
     <Route name="calendar-detail" path="calendar-detail/:id" handler={CalendarDetailPage} />
     <Route name="info-detail" path="info-detail/:id" handler={InfoDetailPage} />
     <Route name="info" handler={InfoPage} />
     <Route name="news" handler={NewsListPage} />
     <Route name="news-detail" path="news-detail/:id" handler={NewsDetailPage} />
     <Route name="contacts" handler={ContactPage} />
     <Route name="contact-detail" handler={ContactDetailPage} />
     <Route name="settings" handler={SettingsPage} />
 </Route>
 );

 Router.run(routes, function(Handler){
   var mountNode = document.getElementById('app');
   React.render(<Handler /> , mountNode);
 });

Wenn Sie eine Lösung gefunden haben, teilen Sie diese bitte hier mit. Vielen Dank.
user261002

Antworten:


43

Ich denke, Sie müssen nur BrowserHistory auf Ihrem Router aktivieren, indem Sie es so initialisieren : <Router history={new BrowserHistory}>.

Zuvor sollten Sie verlangen BrowserHistoryvon'react-router/lib/BrowserHistory'

Ich hoffe das hilft !

UPDATE: Beispiel in ES6

const BrowserHistory = require('react-router/lib/BrowserHistory').default;

const App = React.createClass({
    render: () => {
        return (
            <div><button onClick={BrowserHistory.goBack}>Go Back</button></div>
        );
    }
});

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

Hallo, wir stehen vor dem gleichen Problem. Könnten Sie bitte mehr im Detail erklären. DANKE
user261002

23
Wie ist das die richtige Antwort? Dies beantwortet nicht einmal die Frage. @ Bomber
GN.

14
Für alle, die dies lesen. Wenn Sie dies von einer untergeordneten Komponente aus tun möchten. Sie finden das Verlaufsobjekt unter this.props.history. Also, der Code wirdthis.props.history.goBack
Sisir

3
Wie wäre es mit React-Router 4? Ich glaube nicht, dass es BrowserHistory mehr unterstützt.
Akshay Lokur

1
Ab React-Router-Dom Version 5 wird der Verlauf implizit von BrowserRouter erstellt und ist über die Requisiten verfügbar. Sie können über props.history darauf zugreifen.
Srikanth Kyatham

97

Update mit React v16 und ReactRouter v4.2.0 (Oktober 2017):

class BackButton extends Component {
  static contextTypes = {
    router: () => true, // replace with PropTypes.object if you use them
  }

  render() {
    return (
      <button
        className="button icon-left"
        onClick={this.context.router.history.goBack}>
          Back
      </button>
    )
  }
}

Update mit React v15 und ReactRouter v3.0.0 (August 2016):

var browserHistory = ReactRouter.browserHistory;

var BackButton = React.createClass({
  render: function() {
    return (
      <button
        className="button icon-left"
        onClick={browserHistory.goBack}>
        Back
      </button>
    );
  }
});

Erstellt eine Geige mit einem etwas komplexeren Beispiel mit einem eingebetteten Iframe: https://jsfiddle.net/kwg1da3a/

React v14 und ReacRouter v1.0.0 (10. September 2015)

Du kannst das:

var React = require("react");
var Router = require("react-router");

var SomePage = React.createClass({
  ...

  contextTypes: {
    router: React.PropTypes.func
  },
  ...

  handleClose: function () {
    if (Router.History.length > 1) {
      // this will take you back if there is history
      Router.History.back();
    } else {
      // this will take you to the parent route if there is no history,
      // but unfortunately also add it as a new route
      var currentRoutes = this.context.router.getCurrentRoutes();
      var routeName = currentRoutes[currentRoutes.length - 2].name;
      this.context.router.transitionTo(routeName);
    }
  },
  ...

Sie müssen vorsichtig sein, dass Sie die notwendige Geschichte haben, um zurück zu gehen. Wenn Sie direkt auf die Seite und dann zurück klicken, werden Sie vor Ihrer App wieder in den Browserverlauf aufgenommen.

Diese Lösung berücksichtigt beide Szenarien. Es wird jedoch kein Iframe verarbeitet, der mit der Zurück-Schaltfläche innerhalb der Seite navigieren (und zum Browserverlauf hinzufügen) kann. Ehrlich gesagt denke ich, dass dies ein Fehler im React-Router ist. Hier erstelltes Problem: https://github.com/rackt/react-router/issues/1874


Wäre schön, wenn es eine Möglichkeit gäbe, dies ohne Kontext zu tun?
Adam D

1
Abhängig vom Setup wird möglicherweise auch this.props.history.goBack anstelle von this.context.router.history.goBack
PhoenixB

54
  1. importieren withRouter

    import { withRouter } from 'react-router-dom';
  2. Exportieren Sie Ihre Komponente als:

    export withRouter(nameofcomponent) 
  3. Beispiel goBack: Rufen Sie beim Klicken auf die Schaltfläche Folgendes auf :

    <button onClick={this.props.history.goBack}>Back</button>

Getestet auf react-router-domv4.3


2
Übrigens funktioniert es bei mir auch ohne Import oder Verwendung withRouter. Vielleicht verwenden wir nur die native API für den Browserverlauf. Aber ist das in Ordnung?
Gianfranco P.

1
Das ist eine schöne Lösung. Das einzige Problem, wenn der Benutzer über eine direkte URL auf die Seite gelangt -> wird die App beschädigt, da sie keinen Verlauf hat.
Skryvets

2
Beste Erklärung hier
Z_z_Z

@ MichaelFreidgeim können Sie bitte Ihr Code-Snippet hochladen, damit ich überprüft und verifiziert werde
Gaurav Makwana

43
this.context.router.goBack()

Kein Navigationsmixin erforderlich!


1
Dies funktioniert immer noch in React Router v4, ist es aber this.context.router.history.goBack. (+ Geschichte)
Ben Gotow

13
Mit React-Router-Dom: "v4.2.2" und import { withRouter } from 'react-router-dom';funktioniert mitthis.props.history.goBack();
Felansu

1
Zusätzlich zu @ felansus Kommentar müssen Sie auch Ihre Komponente mit Router exportieren, wie in der Antwort stackoverflow.com/a/49130220/3123338
Mister Q

32

ES6-Methode ohne Mixins mit React-Router, zustandslose Funktion.

import React from 'react'
import { browserHistory } from 'react-router'

export const Test = () => (
  <div className="">
    <button onClick={browserHistory.goBack}>Back</button>
  </div>
)

3
Ich erhalte eine Browser-Warnung, wenn ich Ihre Lösung versuche:export 'browserHistory' was not found in 'react-router'
Ralph David Abernathy

2
browserHistory existiert nur in v2 und v3. Wenn Sie v4 verwenden, sollten Sie das Migrationshandbuch lesen: github.com/ReactTraining/react-router/blob/…
ptorsson

@Ralp, wenn Sie diese Fehlermeldung erhalten, überprüfen Sie dies: stackoverflow.com/questions/49787659/…
Miles M.

13

React Hooks verwenden

Importieren:

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

In zustandsloser Komponente:

  let history = useHistory();

Auf Ereignis

history.goBack()

<button onClick = {() => history.goBack ()}> Zurück </ button>
Hunter

Danke, dass du das erwähnt hast, weil ich Haken mag. Ich habe bisher withRouter verwendet.
Newman

10

Schauen Sie sich mein Arbeitsbeispiel mit React 16.0 mit React-Router v4 Live Example an . Überprüfen Sie den Code Github

Verwenden Sie withRouterundhistory.goBack()

Dies ist die Idee, die ich umsetze ...

History.js

import React, { Component } from 'react';
import { withRouter } from 'react-router-dom'
import './App.css'


class History extends Component {

  handleBack = () => {
    this.props.history.goBack()
  }

  handleForward = () => {
    console.log(this.props.history)
    this.props.history.go(+1)
  }

  render() {
    return <div className="container">
      <div className="row d-flex justify-content-between">
        <span onClick={this.handleBack} className="d-flex justify-content-start button">
          <i className="fas fa-arrow-alt-circle-left fa-5x"></i>
        </span>
        <span onClick={this.handleForward} className="d-flex justify-content-end button">
          <i className="fas fa-arrow-alt-circle-right fa-5x"></i>
        </span>
      </div>
    </div>
  }
}

export default withRouter(History)

PageOne.js

import React, { Fragment, Component } from 'react'

class PageOne extends Component {

   componentDidMount(){
      if(this.props.location.state && this.props.location.state.from != '/pageone')
      this.props.history.push({
         pathname: '/pageone',
         state: { 
             from: this.props.location.pathname
         }
       });
   }

   render() {
      return (
         <Fragment>
            <div className="container-fluid">
               <div className="row d-flex justify-content-center">
                  <h2>Page One</h2>
               </div>
            </div>
         </Fragment>
      )
   }
}

export default PageOne

ps Entschuldigung, der Code ist zu groß, um alles hier zu posten


1
Dies sollte die akzeptierte Antwort ab '19 sein. React Router bietet eine Komponente höherer Ordnung (HOC) mit dem Namen "withRouter", sodass Sie Ihre Komponente einpacken können, um Zugriff auf Requisiten wie Verlauf und Standort zu erhalten.

1
Ja, wie bei withRouter in HOC, wenn Sie Ihr Bauteil einpacken, werden die Verlaufs- und Standortdaten bereitgestellt. Nichts Herausforderndes liest weiter und lässt sich nie nieder.
Anupam Maurya

Darf ich fragen, warum Sie das Pluszeichen an die goFunktion übergeben : history.go(+1)? history.go(1)sollte genug sein.
gion_13

10

Dies funktioniert mit dem Browser- und Hash-Verlauf.

this.props.history.goBack();

8

Dies ist eine funktionierende BackButton-Komponente (React 0.14):

var React = require('react');
var Router = require('react-router');

var History = Router.History;

var BackButton = React.createClass({
  mixins: [ History ],
  render: function() {
    return (
      <button className="back" onClick={this.history.goBack}>{this.props.children}</button>
    );
  }
});

module.exports = BackButton;

Sie können natürlich so etwas tun, wenn es keine Geschichte gibt:

<button className="back" onClick={goBack}>{this.props.children}</button>

function goBack(e) {
  if (/* no history */) {
    e.preventDefault();
  } else {
    this.history.goBack();
  }
}

7

Für den React-Router v2.x hat sich dies geändert. Folgendes mache ich für ES6:

import React from 'react';
import FontAwesome from 'react-fontawesome';
import { Router, RouterContext, Link, browserHistory } from 'react-router';

export default class Header extends React.Component {

  render() {
    return (
      <div id="header">
        <div className="header-left">
          {
            this.props.hasBackButton &&
            <FontAwesome name="angle-left" className="back-button" onClick={this.context.router.goBack} />
          }
        </div>
        <div>{this.props.title}</div>
      </div>
    )
  }
}

Header.contextTypes = {
  router: React.PropTypes.object
};

Header.defaultProps = {
  hasBackButton: true
};

Header.propTypes = {
  title: React.PropTypes.string
};

5

In React-Router v4.x können Sie verwenden, history.goBackwas äquivalent zu ist history.go(-1).

App.js.

import React from "react";
import { render } from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Home from "./Home";
import About from "./About";
import Contact from "./Contact";
import Back from "./Back";

const styles = {
  fontFamily: "sans-serif",
  textAlign: "left"
};

const App = () => (
  <div style={styles}>
    <Router>
      <div>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/contact">Contact</Link></li>
        </ul>

        <hr />

        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/contact" component={Contact} />

        <Back />{/* <----- This is component that will render Back button */}
      </div>
    </Router>
  </div>
);

render(<App />, document.getElementById("root"));

Back.js

import React from "react";
import { withRouter } from "react-router-dom";

const Back = ({ history }) => (
  <button onClick={history.goBack}>Back to previous page</button>
);

export default withRouter(Back);

Demo: https://codesandbox.io/s/ywmvp95wpj

Bitte denken Sie daran, dass durch die Verwendung historyIhrer Benutzer verlassen werden kann, da history.goBack()eine Seite geladen werden kann, die der Besucher vor dem Öffnen Ihrer Anwendung besucht hat.


Um eine solche Situation wie oben beschrieben zu verhindern, habe ich einen einfachen Bibliotheksreaktionsrouter -letzten Speicherort erstellt , der den letzten Speicherort Ihrer Benutzer überwacht.

Die Verwendung ist sehr einfach. Zuerst müssen Sie installieren react-router-domund react-router-last-locationvon npm.

npm install react-router-dom react-router-last-location --save

Dann verwenden Sie LastLocationProviderwie folgt:

App.js.

import React from "react";
import { render } from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { LastLocationProvider } from "react-router-last-location";
//              ↑
//              |
//              |
//
//       Import provider
//
import Home from "./Home";
import About from "./About";
import Contact from "./Contact";
import Back from "./Back";

const styles = {
  fontFamily: "sans-serif",
  textAlign: "left"
};

const App = () => (
  <div style={styles}>
    <h5>Click on About to see your last location</h5>
    <Router>
      <LastLocationProvider>{/* <---- Put provider inside <Router> */}
        <div>
          <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/about">About</Link></li>
            <li><Link to="/contact">Contact</Link></li>
          </ul>

          <hr />

          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
          <Route path="/contact" component={Contact} />

          <Back />
        </div>
      </LastLocationProvider>
    </Router>
  </div>
);

render(<App />, document.getElementById("root"));

Back.js

import React from "react";
import { Link } from "react-router-dom";
import { withLastLocation } from "react-router-last-location";
//              ↑
//              |
//              |
//
//    `withLastLocation` higher order component
//    will pass `lastLocation` to your component               
//
//                   |
//                   |
//                   ↓
const Back = ({ lastLocation }) => (
  lastLocation && <Link to={lastLocation || '/'}>Back to previous page</Link>
);


//          Remember to wrap
//   your component before exporting
//
//                   |
//                   |
//                   ↓
export default withLastLocation(Back);

Demo: https://codesandbox.io/s/727nqm99jj


Wie würden Sie das LastLocation-Objekt einfach in die Komponente ziehen, die es benötigt - das heißt, ich möchte es programmgesteuert verwenden und nicht in einer angezeigten Ausgabe wie Ihren Beispielen: if (lastLocation == 'about')
dmayo

Ich bin mir nicht sicher, ob ich dich richtig verstanden habe. Bitte korrigiere mich, wenn ich falsch liege. Möchten Sie lastLocationaußerhalb des React verwenden oder I'd like to use it programmaticallymöchten Sie vielleicht sagen , möchten Sie nur die Möglichkeit haben, es wie zu importieren import { lastLocation } from '...'?
Hinok

5

Was für mich funktionierte, war das Importieren mit Router oben in meiner Datei;

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

Verwenden Sie es dann, um die exportierte Funktion am Ende meiner Datei zu verpacken.

export default withRouter(WebSitePageTitleComponent)

Dadurch konnte ich auf die Verlaufs-Requisite des Routers zugreifen. Vollständiger Beispielcode unten!

import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'

import PropTypes from 'prop-types'

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

  handleClick() {
    event.preventDefault()
    this.props.history.goBack()
  }

  render() {
    return (
      <div className="page-title">
        <a className="container" href="/location" onClick={this.handleClick}>
          <h1 className="page-header">
            { this.props.title }
          </h1>
        </a>
      </div>
    )
  }
}

const { string, object } = PropTypes

TestComponent.propTypes = {
  title: string.isRequired,
  history: object
}

export default withRouter(TestComponent)

5

Gehen Sie zurück zu einer bestimmten Seite :

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

  const history = useHistory();
  
  const routeChange = () => {
    let path = '/login';
    history.push(path);
  };

Zurück zur vorherigen Seite:

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

  const history = useHistory();
  
  const routeChange = () => {
    history.goBack()
  };

2
Danke, das ist eine großartige Antwort für 2020! Die akzeptierte Antwort war so 2015.
beeftosino

3
import { withRouter } from 'react-router-dom'

this.props.history.goBack();

Ich benutze diese Versionen

"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",

2

Die einzige Lösung, die für mich funktioniert hat, war die einfachste. Keine zusätzlichen Importe erforderlich.

<a href="#" onClick={() => this.props.history.goBack()}>Back</a>

Tks, IamMHussain


Sehr schön. Einfach und bescheiden
Dinesh Kanivu

1

Nennen Sie die folgende Komponente wie folgt:

<BackButton history={this.props.history} />

Und hier ist die Komponente:

import React, { Component } from 'react'
import PropTypes from 'prop-types'
class BackButton extends Component {
  constructor() {
    super(...arguments)

    this.goBack = this.goBack.bind(this)
  }

  render() {
    return (
      <button
        onClick={this.goBack}>
          Back
      </button>
    )
  }

  goBack() {
    this.props.history.goBack()
  }
}

BackButton.propTypes = {
  history: PropTypes.object,
}

export default BackButton

Ich benutze:

"react": "15.6.1"
"react-router": "4.2.0"

1

REDUXIEREN

Sie können auch verwenden, react-router-reduxwas hat goBack()und push().

Hier ist ein Sampler Pack dafür:

Im Einstiegspunkt Ihrer App benötigen Sie ConnectedRouter, und eine manchmal schwierige Verbindung zum Anschließen ist das historyObjekt. Die Redux-Middleware hört Änderungen im Verlauf ab:

import React from 'react'
import { render } from 'react-dom'
import { ApolloProvider } from 'react-apollo'
import { Provider } from 'react-redux'
import { ConnectedRouter } from 'react-router-redux'
import client from './components/apolloClient'
import store, { history } from './store'
import Routes from './Routes'
import './index.css'

render(
  <ApolloProvider client={client}>
    <Provider store={store}>
      <ConnectedRouter history={history}>
        <Routes />
      </ConnectedRouter>
    </Provider>
  </ApolloProvider>,
  document.getElementById('root'),
)

Ich werde Ihnen einen Weg zeigen, das anzuschließen history. Beachten Sie, wie der Verlauf in den Store importiert und auch als Singleton exportiert wird, damit er im Einstiegspunkt der App verwendet werden kann:

import { createStore, applyMiddleware, compose } from 'redux'
import { routerMiddleware } from 'react-router-redux'
import thunk from 'redux-thunk'
import createHistory from 'history/createBrowserHistory'
import rootReducer from './reducers'

export const history = createHistory()

const initialState = {}
const enhancers = []
const middleware = [thunk, routerMiddleware(history)]

if (process.env.NODE_ENV === 'development') {
  const { devToolsExtension } = window
  if (typeof devToolsExtension === 'function') {
    enhancers.push(devToolsExtension())
  }
}

const composedEnhancers = compose(applyMiddleware(...middleware), ...enhancers)
const store = createStore(rootReducer, initialState, composedEnhancers)

export default store

Der obige Beispielblock zeigt, wie die react-router-reduxMiddleware-Helfer geladen werden, die den Setup-Vorgang abschließen.

Ich denke, dieser nächste Teil ist komplett extra, aber ich werde ihn aufnehmen, nur für den Fall, dass jemand in Zukunft Nutzen findet:

import { combineReducers } from 'redux'
import { routerReducer as routing } from 'react-router-redux'

export default combineReducers({
  routing, form,
})

Ich benutze die routerReducerganze Zeit, weil es mir erlaubt, das Neuladen von Komponenten zu erzwingen, die normalerweise nicht aufgrund von shouldComponentUpdate. Das offensichtliche Beispiel ist, wenn Sie eine Navigationsleiste haben, die aktualisiert werden soll, wenn ein Benutzer eine NavLinkTaste drückt . Wenn Sie diesen Weg gehen, werden Sie erfahren, dass die Verbindungsmethode von Redux verwendet shouldComponentUpdate. Mit routerReducerkönnen Sie mapStateToPropsRouting-Änderungen in der Navigationsleiste zuordnen. Dadurch wird die Aktualisierung ausgelöst, wenn sich das Verlaufsobjekt ändert.

So was:

const mapStateToProps = ({ routing }) => ({ routing })

export default connect(mapStateToProps)(Nav)

Verzeihen Sie mir, während ich einige zusätzliche Schlüsselwörter für Personen hinzufüge: Wenn Ihre Komponente nicht ordnungsgemäß aktualisiert wird, überprüfen Sie dies, shouldComponentUpdateindem Sie die Verbindungsfunktion entfernen und prüfen, ob das Problem dadurch behoben wird. Wenn dies der Fall ist, ziehen Sie die routerReducerund die Komponente wird ordnungsgemäß aktualisiert, wenn sich die URL ändert.

Abschließend können Sie nach all dem anrufen goBack()oder push()jederzeit!

Versuchen Sie es jetzt in einer zufälligen Komponente:

  1. Importieren in connect()
  2. Du brauchst nicht einmal mapStateToPropsodermapDispatchToProps
  3. In goBack importieren und von drücken react-router-redux
  4. Anruf this.props.dispatch(goBack())
  5. Anruf this.props.dispatch(push('/sandwich'))
  6. Erleben Sie positive Emotionen

Wenn Sie weitere Stichproben benötigen, besuchen Sie: https://www.npmjs.com/package/react-router-redux


1

Einfach so verwenden

<span onClick={() => this.props.history.goBack()}>Back</span>

0

Dieser Code erledigt den Trick für Sie.

this.context.router.history.goBack()

0

Reagiere auf Router v6

useNavigate Hook ist der empfohlene Weg, um jetzt zurückzukehren:

import { useNavigate } from 'react-router-dom';

function App() {
  const navigate = useNavigate();

  return (
    <>
      <button onClick={() => navigate(-1)}>go back</button>
      <button onClick={() => navigate(1)}>go forward</button>
    </>
  );
}

Codesandbox-Beispiel

Gehen Sie mehrere Verlaufsstapeleinträge vor / zurück:
<button onClick={() => navigate(-2)}>go two back</button>
<button onClick={() => navigate(2)}>go two forward</button>
Gehen Sie zu einer bestimmten Route:
navigate("users") // go to users route, like history.push
navigate("users", { replace: true }) // go to users route, like history.replace
navigate("users", { state }) // go to users route, pass some state in

useNavigate ersetzt useHistory , um den kommenden React Suspense / Concurrent-Modus besser zu unterstützen.


Ich habe versucht, dies zu versuchen, aber ich habe den Fehler erhalten:Attempted import error: 'useNavigate' is not exported from 'react-router-dom'.
Geek

1
@ Geek guten Fang. Mit v6.0.0-beta.0haben Entwickler das historyPaket zu einer Peer-Abhängigkeit gemacht. Schauen Sie sich die aktualisierte Codesandbox an, die jetzt wieder funktioniert.
Ford04

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.