156
votes

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);
 });
23
if you have found a solution, could you please, share it here. thanks.user261002

23 Answers

60
votes

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);
114
votes

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

75
votes

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>
58
votes
  1. import withRouter

    import { withRouter } from 'react-router-dom';
    
  2. Export your component as:

    export withRouter(nameofcomponent) 
    
  3. Example, on button click, call goBack:

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

Tested on react-router-dom v4.3

43
votes
this.context.router.goBack()

No navigation mixin required!

33
votes

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>
)
20
votes

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()
  };
11
votes

Check out my working example using React 16.0 with React-router v4 Live Example. 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

11
votes

This works with Browser and Hash history.

this.props.history.goBack();
8
votes

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();
  }
}
7
votes

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
};
7
votes

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

7
votes

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.

5
votes

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)
3
votes
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",
2
votes

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:

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

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

2
votes

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

1
votes

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"
1
votes

Simply use like this

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

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>
0
votes

This piece of code will do the trick for you.

this.context.router.history.goBack()
0
votes
`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>`
-1
votes

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