Reputation: 1068
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
Reputation: 168
I am having the below problems when handling the back button in React:
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
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
Reputation: 666
I had a similar issue and fixed that this way:
componentDidUpdate(){
window.onpopstate = (e) => {
// Tour code...
}
}
Upvotes: 4
Reputation: 31
Try this code:
componentDidMount() {
window.addEventListener("popstate", this.onBackButtonEvent)
}
componentWillUnmount() {
window.removeEventListener("popstate", this.onBackButtonEvent)
}
onBackButtonEvent = () => {
window.history.forward()
}
Upvotes: 1