ChatGPT解决这个技术问题 Extra ChatGPT

react-router go back a page how do you configure history?

Can anyone please tell me how I can go back to the previous page rather than a specific route?

When using this code:

var BackButton = React.createClass({

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

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

Get this error, goBack() was ignored because there is no router history

Here are my routes:

// 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);
 });

B
Ben Gotow

Update with React v16 and ReactRouter v4.2.0 (October 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 with React v15 and 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>
    );
  }
});

Created a fiddle with a little bit more complex example with an embedded iframe: https://jsfiddle.net/kwg1da3a/

React v14 and ReacRouter v1.0.0 (Sep 10, 2015)

You can do this:

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);
    }
  },
  ...

You need to be careful that you have the necessary history to go back. If you hit the page directly and then hit back it will take you back in the browser history before your app.

This solution will take care of both scenarios. It will, however, not handle an iframe that can navigate within the page (and add to the browser history), with the back button. Frankly, I think that is a bug in the react-router. Issue created here: https://github.com/rackt/react-router/issues/1874


Would be nice if there was a way to do this without using context?
Also, depending on setup, might be using this.props.history.goBack instead of this.context.router.history.goBack
E
Eric Roberto

Using React Hooks

Import:

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

In stateless component:

let history = useHistory();

Call the Event:

history.goBack()

Examples do use in event Button:

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

or

<button onClick={() => history.goBack()}>Back</button>

Thanks for mentioning this because I like hooks. I have been using withRouter so far.
'useHistory' is not exported from 'react-router-dom'.
@Hunter thanks i was doin onClick={history.goBack()} then its gettin clicked without clicking
passing the function as is also works <button onClick={history.goBack}>Back</button> (without the parenthesis)
G
Gianfranco P.

import withRouter import { withRouter } from 'react-router-dom'; Export your component as: export withRouter(nameofcomponent) Example, on button click, call goBack:

Tested on react-router-dom v4.3


BTW it works for me even without importing or using withRouter. Maybe we're just using the browser history native API. But is that ok??
That's nice solution. The only problem when user lands to the page using direct URL -> it will break the app as it doesn't have history.
Best explanation here
@MichaelFreidgeim can you please upload your code snippet so i will checked and verified
K
Kenny Horna

I think you just need to enable BrowserHistory on your router by intializing it like that : <Router history={new BrowserHistory}>.

Before that, you should require BrowserHistory from 'react-router/lib/BrowserHistory'

I hope that helps !

UPDATE : example 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);

hi, we are facing the same problem. could you please explain more in details. THANKS
How is this the correct answer? This doesn't even answer the question. @bomber
For anyone reading this. If you want to do this from a child component. You can find the history object at this.props.history. So, the code becomes this.props.history.goBack
How about react-router 4? I don't think it supports BrowserHistory any more.
As of react-router-dom version 5, history is created by BrowserRouter implicitly and is available via the props, you could access it via props.history.
a
ahhhhhhhhhhhhhhhhhhhhhhhhhhhhh
this.context.router.goBack()

No navigation mixin required!


This still works in React Router v4, but it's this.context.router.history.goBack. (+history)
With react-router-dom: "v4.2.2" and import { withRouter } from 'react-router-dom'; works with this.props.history.goBack();
in addition to @felansu's comment you need also to export your component withRouter as explained in the answer stackoverflow.com/a/49130220/3123338
p
ptorsson

ES6 method without mixins using react-router, stateless function.

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

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

I get a browser warning when trying your solution: export 'browserHistory' was not found in 'react-router'
browserHistory only exist in v2 and v3. If you use v4 you should read the migration guide: github.com/ReactTraining/react-router/blob/…
@Ralp, if you get this error message, check this out: stackoverflow.com/questions/49787659/…
C
Community

React Router v6

useNavigate Hook is the recommended way to go back now:

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 sample

<button onClick={() => navigate(-2)}>go two back</button>
<button onClick={() => navigate(2)}>go two forward</button>
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 replaces useHistory to support upcoming React Suspense/Concurrent mode better.


I tried to attempt this but I got the error: Attempted import error: 'useNavigate' is not exported from 'react-router-dom'.
@Geek good catch. With v6.0.0-beta.0, devs have made the history package a peer dependency. Take a look at the updated Codesandbox, which works again now.
I tried this. But it gives me "Uncaught TypeError: Object(...) is not a function" error. Does anyone know the issue? If so please explain
Shouldn't use }> instead of
d
dhahn

Go back to specific page:

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

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

Go back to previous page:

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

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

M
Morris S

Check out my working example using React 16.0 with React-router v4. check out the code Github

Use withRouter and history.goBack()

This is the idea I am implementing...

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

p.s. sorry the code is to big to post it all here


This should be the accepted answer as of '19. React Router provides a higher order component (HOC) called "withRouter" so you can wrap your component to have access to props such as history and location.
yes as in withRouter in HOC in your wrapping up your component part, will provide the history and location data. Nothing challenging keeps reading and never settle.
May I ask why you pass the plus sign to the go function: history.go(+1)? history.go(1) should be enough.
honestly I just tried using this history.goBack() without withRouter already did the trick
S
Sunil kumawat

This works with Browser and Hash history.

this.props.history.goBack();

n
ngstschr

This is a working BackButton component (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;

You can off course do something like this if there is no history:

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

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

a
aceofspades

For react-router v2.x this has changed. Here's what I'm doing for 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
};

D
Dawid Karabin

In react-router v4.x you can use history.goBack which is equivalent to 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

Please remember that by using history your users can leave because history.goBack() can load a page that visitor has visited before opening your application.

To prevent such situation as described above, I've created a simple library react-router-last-location that watch your users last location.

Usage is very straight forward. First you need to install react-router-dom and react-router-last-location from npm.

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

Then use LastLocationProvider as below:

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


How would you just pull in the LastLocation object into the component that needs it -- that is, I'd like to use it programmatically, rather than in some displayed output like your examples: if(lastLocation == 'about')
Not sure if I understood you correctly, so please correct me if I'm wrong. Would you like to use lastLocation outside of the React or maybe by saying I'd like to use it programmatically, do you want to just have ability to import it like import { lastLocation } from '...'?
v
vancy-pants

What worked for me was to import withRouter at the top of my file;

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

Then use it to wrap the exported function at the bottom of my file;

export default withRouter(WebSitePageTitleComponent)

Which then allowed me to access the Router's history prop. Full sample code below!

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)

S
Shubhrajyoti Dey

I want to update the previous answers a bit. If you are using react-router >v6.0 then the useHistory() is not the right way to go back. You will get an error as I guess useHistory() is not present in the latest version. So this is the updated answer

// This is a React Router v6 app
import { useNavigate } from "react-router-dom";

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

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

Use this useNavigate() hook. You can read the official doc for this transition from v5 to v6 here https://reactrouter.com/docs/en/v6/upgrading/v5


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

this.props.history.goBack();

I am using these versions

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

M
Muhammad Usama Ashraf

Step-1

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

Step-2

let history = useHistory();

Step-3

const goToPreviousPath = (e) => {
   e.preventDefault();
   history.goBack()
}

step-4

<Button
  onClick={goToPreviousPath}
>
  Back
</Button>

i
iku

On react-router-dom v6

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

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

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

a
agm1984

REDUX

You can also use react-router-redux which has goBack() and push().

Here is a sampler pack for that:

In your app's entry point, you need ConnectedRouter, and a sometimes tricky connection to hook up is the history object. The Redux middleware listens to history changes:

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'),
)

I will show you a way to hook up the history. Notice how the history is imported into the store and also exported as a singleton so it can be used in the app's entry point:

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

The above example block shows how to load the react-router-redux middleware helpers which complete the setup process.

I think this next part is completely extra, but I will include it just in case someone in the future finds benefit:

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

export default combineReducers({
  routing, form,
})

I use routerReducer all the time because it allows me to force reload Components that normally do not due to shouldComponentUpdate. The obvious example is when you have a Nav Bar that is supposed to update when a user presses a NavLink button. If you go down that road, you will learn that Redux's connect method uses shouldComponentUpdate. With routerReducer, you can use mapStateToProps to map routing changes into the Nav Bar, and this will trigger it to update when the history object changes.

Like this:

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

export default connect(mapStateToProps)(Nav)

Forgive me while I add some extra keywords for people: if your component isn't updating properly, investigate shouldComponentUpdate by removing the connect function and see if it fixes the problem. If so, pull in the routerReducer and the component will update properly when the URL changes.

In closing, after doing all that, you can call goBack() or push() anytime you want!

Try it now in some random component:

Import in connect() You don't even need mapStateToProps or mapDispatchToProps Import in goBack and push from react-router-redux Call this.props.dispatch(goBack()) Call this.props.dispatch(push('/sandwich')) Experience positive emotion

If you need more sampling, check out: https://www.npmjs.com/package/react-router-redux


I
IamMHussain

Simply use like this

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

J
JBarros

The only solution that worked for me was the most simple. No additional imports needed.

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

Tks, IamMHussain


Very Nice. Simple and Humble
J
Jetwiz

React Router uses the HTML5 History API, which builds on the browser history API to provide an interface to which we can use easily in React apps. History API . So without import anything (useHistory, etc)

for functional component:

<button onClick={()=>{ window.history.back() }}> Back </button>

for class component:

<button onClick={()=>{ this.window.history.back() }}> Back </button>

G
Gal Bracha

Call the following component like so:

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

And here is the component:

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

I'm using:

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

p
prajeesh

This piece of code will do the trick for you.

this.context.router.history.goBack()

L
Lane

According to https://reacttraining.com/react-router/web/api/history

For "react-router-dom": "^5.1.2",,

const { history } = this.props;
<Button onClick={history.goBack}>
  Back
</Button>
YourComponent.propTypes = {
  history: PropTypes.shape({
    goBack: PropTypes.func.isRequired,
  }).isRequired,
};