dhrDatt
dhrDatt

Reputation: 1068

Browser back button using React

I am using React. I want to warn the user when the user clicks on the back button.

What I had done was

handleWindowClose = (ev) => {
    ev.preventDefault();
    return ev.returnValue = 'Leaving this page will loose data';
}

componentDidMount = () => {
    window.addEventListener('beforeunload',this.handleWindowClose);
}

componentWillUnmount = () => {
    window.removeEventListener('beforeunload',this.handleWindowClose);
}

However, this does not work with a back button click. So I tried doing this:

handleWindowClose = (ev) => {
    ev.preventDefault();
    return ev.returnValue = 'Leaving this page will loose data';
}

onBackButtonEvent = (e) => {
    e.preventDefault();
    if (confirm("Do you want to loose this data")) {
        window.history.go(0);
    }
    else {
        window.history.forward();
    }
}

componentDidMount = () => {
    window.addEventListener('beforeunload',this.handleWindowClose);
    window.addEventListener('popstate',this.onBackButtonEvent);
}

componentWillUnmount = () => {
    window.removeEventListener('beforeunload',this.handleWindowClose);
    window.removeEventListener('popstate',this.onBackButtonEvent);
}

I am not using react-router. Is there a better way to do this using only React? Also I want the window to stay on that page without using history.forward() as I will lose the window state.

Upvotes: 10

Views: 36471

Answers (4)

I am having the below problems when handling the back button in React:

  1. The first popstate event is not being called at the first time
  2. It is called twice after executing my back button custom logic

To solve problem 1, I did the following code:

componentDidMount() {
    window.history.pushState(null, null, window.location.pathname);
    window.addEventListener('popstate', this.onBackButtonEvent);
}

To solve problem 2, I did the below code:

onBackButtonEvent = (e) => {
    e.preventDefault();

    if (!this.isBackButtonClicked) {
        if (window.confirm("Do you want to save your changes")) {
            this.isBackButtonClicked = true;
            // Your custom logic to page transition, like react-router-dom history.push()
        }
        else {
            window.history.pushState(null, null, window.location.pathname);
            this.isBackButtonClicked = false;
        }
    }
}

Don't forget to add this.isBackButtonClicked = false; in the constructor and unscubscribe the events.

componentWillUnmount = () => {
    window.removeEventListener('popstate', this.onBackButtonEvent);
}

Upvotes: 7

U r s u s
U r s u s

Reputation: 6968

It looks like onbeforeunload is what you want: check this related question, which contains a useful demo.

Also the MDN documentation contain a useful example.


Assuming you've got some good reason for not wanting to use react-router, I'll sketch the JavaScript way of doing this

It looks like you're capturing the wrong event. You want to grab any change of the URL hash, so you should use onhashchange.

Example from the documentation:

if ("onhashchange" in window) {
    alert("The browser supports the hashchange event!");
}

function locationHashChanged() {
    if (location.hash === "#somecoolfeature") {
        somecoolfeature();
    }
}

window.onhashchange = locationHashChanged;

However, I'd give react-router a go, given that you're developing in React. In which case, browserHistory would be your friend.

Upvotes: 1

Viraj
Viraj

Reputation: 666

I had a similar issue and fixed that this way:

componentDidUpdate(){
  
    window.onpopstate  = (e) => {
        // Tour code...
    }      
}

Upvotes: 4

Darshan Dixit
Darshan Dixit

Reputation: 31

Try this code:

componentDidMount() {
    window.addEventListener("popstate", this.onBackButtonEvent)
}

componentWillUnmount() {
  window.removeEventListener("popstate", this.onBackButtonEvent)
}

onBackButtonEvent = () => {
    window.history.forward()
}

Upvotes: 1

Related Questions