react-router (v4) how to go back?

Trying to figure out how can I go back to the previous page. I am using [react-router-v4][1]

This is the code I have configured in my first landing page:

<Router>
  <div>
    <Link to="/"><div className="routerStyle"><Glyphicon glyph="home" /></div></Link>
    <Route exact path="/" component={Page1}/>
    <Route path="/Page2" component={Page2}/>
    <Route path="/Page3" component={Page3}/>
  </div>
</Router>

In order to forward to subsequent pages, I simply do:

this.props.history.push('/Page2');

However, how can I go back to previous page? Tried few things like mentioned below but no luck: 1. this.props.history.goBack();

Gives error:

TypeError: null is not an object (evaluating 'this.props')

  1. this.context.router.goBack();

Gives error:

TypeError: null is not an object (evaluating 'this.context')

  1. this.props.history.push('/');

Gives error:

TypeError: null is not an object (evaluating 'this.props')

Posting the Page1 code here below:

import React, {Component} from 'react';
import {Button} from 'react-bootstrap';

class Page1 extends Component {
  constructor(props) {
    super(props);
    this.handleNext = this.handleNext.bind(this);
  }


  handleNext() {
    this.props.history.push('/page2');
  }

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


  /*
   * Main render method of this class
   */
  render() {
    return (
      <div>
        {/* some component code */}


        <div className="navigationButtonsLeft">
          <Button onClick={this.handleBack} bsStyle="success">&lt; Back</Button>
        </div>
        <div className="navigationButtonsRight">
          <Button onClick={this.handleNext} bsStyle="success">Next &gt;</Button>
        </div>

      </div>
    );
  }


export default Page1;

I think the issue is with binding:

constructor(props){
   super(props);
   this.goBack = this.goBack.bind(this); // i think you are missing this
}

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

.....

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

As I have assumed before you posted the code:

constructor(props) {
    super(props);
    this.handleNext = this.handleNext.bind(this);
    this.handleBack = this.handleBack.bind(this); // you are missing this line
}

UPDATED:

Now we have hook, so we can do it easily by using useHistory

const history = useHistory()

const goBack = () => {
  history.goBack()
}

return (
  <button type="button" onClick={goBack}>
    Go back
  </button>
);

ORIGINAL POST:

this.props.history.goBack();

This is the correct solution for react-router v4

But one thing you should keep in mind is that you need to make sure this.props.history is existed.

That means you need to call this function this.props.history.goBack(); inside the component that is wrapped by < Route/>

If you call this function in a component that deeper in the component tree, it will not work.

EDIT:

If you want to have history object in the component that is deeper in the component tree (which is not wrapped by < Route>), you can do something like this:

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

class Demo extends Component {
    ...
    // Inside this you can use this.props.history.goBack();
}

export default withRouter(Demo);

For use with React Router v4 and a functional component anywhere in the dom-tree.

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

const GoBack = ({ history }) => <img src="./images/back.png" onClick={() => history.goBack()} alt="Go back" />;

export default withRouter(GoBack);

Each answer here has parts of the total solution. Here's the complete solution that I used to get it to work inside of components deeper than where Route was used:

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

^ You need that second line to import function and to export component at bottom of page.

render() {
  return (
  ...
    <div onClick={() => this.props.history.goBack()}>GO BACK</div>
  )
}

^ Required the arrow function vs simply onClick={this.props.history.goBack()}

export default withRouter(MyPage)

^ wrap your component's name with 'withRouter()'


Here is the cleanest and simplest way you can handle this problem, which also nullifies the probable pitfalls of the this keyword. Use functional components:

import { withRouter } from "react-router-dom"; wrap your component or better App.js with the withRouter() HOC this makes history to be available "app-wide". wrapping your component only makes history available for that specific component``` your choice.

So you have:

  1. export default withRouter(App);

  2. In a Redux environment export default withRouter( connect(mapStateToProps, { <!-- your action creators -->})(App), ); you should even be able to user history from your action creators this way.

in your component do the following:

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

const history = useHistory(); // do this inside the component

goBack = () => history.goBack();

<btn btn-sm btn-primary onclick={goBack}>Go Back</btn>

export default DemoComponent;

Gottcha useHistory is only exported from the latest v5.1 react-router-dom so be sure to update the package. However, you should not have to worry. about the many snags of the this keyword.

You can also make this a reusable component to use across your app.


function BackButton({ children }) {
  let history = useHistory()
  return (
    <button type="button" onClick={() => history.goBack()}>
      {children}
    </button>
  )
}```
Cheers.