Is there some event I can subscribe to when the history state is modified? How?
2 Answers
I used to use this to also be notified of when pushState and replaceState are called:
// Add this:
var _wr = function(type) {
var orig = history[type];
return function() {
var rv = orig.apply(this, arguments);
var e = new Event(type);
e.arguments = arguments;
window.dispatchEvent(e);
return rv;
};
};
history.pushState = _wr('pushState'), history.replaceState = _wr('replaceState');
// Use it like this:
window.addEventListener('replaceState', function(e) {
console.warn('THEY DID IT AGAIN!');
});
It's usually overkill though. And it might not work in all browsers. (I only care about my version of my browser.)
NB. It also doesn't work in Google Chrome extension content scripts, because it's not allowed to alter the site's JS environment. You can work around that by inserting a <script> with said code, but that's even more overkill.
- 49,688
- 40
- 128
- 172
The onpopstate event should be fired when the history changes, you can bind to it in your code like this:
window.onpopstate = function (event) {
// do stuff here
}
This event may also be fired when the page loads, you can determine whether the event was fired from a page load, or by using pushState/replaceState by checking the event object for a state property, it will be undefined if the event was caused by a page load
window.onpopstate = function (event) {
if (event.state) {
// history changed because of pushState/replaceState
} else {
// history changed because of a page load
}
}
There currently is no onpushstate event unfortunately, to get around this you need to wrap both the pushState and replaceState methods to implement your own onpushstate event.
I have a library that makes working with pushState a bit easier, it might be worth checking it out called Davis.js, it provides a simple api for working with routing based on pushState.
- 2,212
- 1
- 17
- 23
-
It seems that event.state might still be set on page load (Chrome). – GolezTrol Jul 20 '11 at 15:29
-
3Mozilla/Firefox doesn't emit a onpopstate event on page load but Safari/Chrome do – tom Jul 23 '12 at 23:25
-
In my case, this event takes place after success of an ajax call. Possibly due to this, i'm not able to detect the event for the first time. If i click back/forward button then it works good however i'm not expecting my user to click those history buttons. – Tushar Shukla Aug 06 '16 at 17:55
-
113The [docs](https://developer.mozilla.org/en-US/docs/Web/Events/popstate) explicitly state that `pushState` does NOT fire `onpopstate`! – abalter Apr 05 '18 at 08:26
-
This answer is incorrect. According to docs onpopstate is fired in case of history.back(), history.forward(), history.go(). How is is this the accepted answer. – Viraj Singh Oct 01 '21 at 17:42