104

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;
Akshay Lokur
  • 4,868
  • 11
  • 36
  • 51

13 Answers13

140

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
}
Vivek Doshi
  • 46,471
  • 9
  • 84
  • 100
  • doesn't work when browser back button is pressed and in `componentDidUpdate` and `window.onpopstate`? – jmunsch Mar 02 '20 at 21:08
36

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);
Hoang Trinh
  • 2,253
  • 1
  • 24
  • 47
  • So how can it work? How can you go back in history from anywhere? – Felipe Jun 28 '18 at 22:56
  • @Felipe You can go back from anywhere. I just mean that you need to add this line of code in the Container components in order to get the "history" object, don't use this line of code from Presentational components that is not wrapped by Route (https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0) – Hoang Trinh Jun 29 '18 at 05:01
  • @Felipe: Hi, please check my edited answer. I think it answers your question. – Hoang Trinh Jul 08 '18 at 05:09
  • Thank you for the withRouter edit, that fixed it for me. – Matthew Rideout Aug 10 '19 at 22:32
18

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);
frippera
  • 181
  • 1
  • 4
  • This is a good solution because it does not use a lifecycle method. It is also clearer to me because it denotes what gets passed through, in this case the history object. – AC Patrice Jun 17 '19 at 01:59
  • The fat arrow version always looks much cleaner to me, thanks for that. – egdavid Jul 25 '19 at 08:42
10

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

foureyedraven
  • 171
  • 3
  • 12
7

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.

Mazyod
  • 21,361
  • 9
  • 86
  • 147
Lawrence Eagles
  • 351
  • 4
  • 7
5

Can you provide the code where you use this.props.history.push('/Page2');?

Have you tried the goBack() method?

this.props.history.goBack();

It's listed here https://reacttraining.com/react-router/web/api/history

With a live example here https://reacttraining.com/react-router/web/example/modal-gallery

Alfredo Re
  • 112
  • 7
0

Try:

this.props.router.goBack()
Rodius
  • 1,959
  • 11
  • 19
  • This gives me error, please see updated question above – Akshay Lokur Oct 11 '17 at 06:46
  • where are you getting your router or history prop from? Make sure you're getting it from your parent component or page (i.e console.log(this.props) on the render function and check that you're printing the router prop in order to be able to use it. Seems to me you don't have router in your component. – Rodius Oct 11 '17 at 06:52
0

Simply use

<span onClick={() => this.props.history.goBack()}>Back</span>
IamMHussain
  • 587
  • 7
  • 10
0

Hope this will help someone:

import React from 'react';
import * as History from 'history';
import { withRouter } from 'react-router-dom';

interface Props {
  history: History;
}

@withRouter
export default class YourComponent extends React.PureComponent<Props> {

  private onBackClick = (event: React.MouseEvent): void => {
    const { history } = this.props;
    history.goBack();
  };

...
Nick Bristol
  • 64
  • 1
  • 3
0

Maybe this can help someone.

I was using history.replace() to redirect, so when i tried to use history.goBack(), i was send to the previous page before the page i was working with. So i changed the method history.replace() to history.push() so the history could be saved and i would be able to go back.

0

I am not sure if anyone else ran into this problem or may need to see this. But I spent about 3 hours trying to solve this issue:

I wanted to implement a simple goBack() on the click of a button. I thought I was off to a good start because my App.js was already wrapped in the Router and I was importing { BrowserRouter as Router } from 'react-router-dom'; ... Since the Router element allows me to assess the history object.

ex:

import React from 'react';
import './App.css';
import Splash from './components/Splash';
import Header from './components/Header.js';
import Footer from './components/Footer';
import Info from './components/Info';
import Timer from './components/Timer';
import Options from './components/Options';
import { BrowserRouter as Router, Route } from 'react-router-dom';
function App() {
  return (
    <Router>
      <Header />
      <Route path='/' component={Splash} exact />
      <Route path='/home' component={Info} exact />
      <Route path='/timer' component={Timer} exact />
      <Route path='/options' component={Options} exact />
      <Footer />
    </Router>
  );
}
export default App;

BUT the trouble was on my Nav (a child component) module, I had to 'import { withRouter } from 'react-router-dom';' and then force an export with:

export default withRouter(Nav);

ex:

import React from 'react';
import { withRouter } from 'react-router-dom';
class Nav extends React.Component {
    render() {
        return (
            <div>
                <label htmlFor='back'></label>
                <button id='back' onClick={ () => this.props.history.goBack() }>Back</button>
                <label htmlFor='logOut'></label>
                <button id='logOut' ><a href='./'>Log-Out</a>            
</button>
            </div>
        );
    }
}
export default withRouter(Nav);

in summary, withRouter was created because of a known issue in React where in certain scenarios when inheritance from a router is refused, a forced export is necessary.

0

You can use history.goBack() in functional component. Just like this.

import { useHistory } from 'react-router';
const component = () => { 
  const history = useHistory();

  return (
   <button onClick={() => history.goBack()}>Previous</button>
  )
}
Zeeshan Safdar
  • 306
  • 1
  • 3
  • 10
0

If using react hooks just do:

import { useHistory } from "react-router-dom";
const history = useHistory();
history.go(-1);
Tovi Newman
  • 390
  • 3
  • 9