history.pushState does not trigger 'popstate' event
Asked Answered
R

6

30

Why

window.addEventListener('popstate', () => alert('pop'));

window.history.pushState(null, '', '/foo');

does not alert pop ?

NB: Testing on latest chrome

--

According to MDN:

A popstate event is dispatched to the window every time the active history entry changes. If the history entry being activated was created by a call to pushState or affected by a call to replaceState, the popstate event's state property contains a copy of the history entry's state object.

So why my pushState does not trigger the popstate event?

Romantic answered 7/6, 2012 at 22:39 Comment(0)
G
16

The paragraph you reference is a little ambiguous. Reading the example on the same page, it is clear that popstate is only triggered when the user clicks the back button, not when the script calls pushState().

Georas answered 8/6, 2012 at 10:41 Comment(4)
popstate is also triggered when the user presses the forward button.Inoffensive
pushstate does trigger popstate! Hence "A popstate event is dispatched to the window every time the active history entry changes"!Arteriosclerosis
@AlexGill Do you have a test-case that demonstrates this behavior? Something like: ` window.onpopstate = function(e) { alert('popstate'); } history.pushState(null, ''); `Georas
popstate is also triggered with window.location.hash = "<some new hash>". Dmitri Farkov's answer below mentions this detail and it's important I think.Eucharis
H
65

You can manually trigger popstate event on window every time you call history.pushState().

history.pushState(state, '', url);

var popStateEvent = new PopStateEvent('popstate', { state: state });
dispatchEvent(popStateEvent);
Hayner answered 27/5, 2016 at 20:52 Comment(2)
Excellent answer, Thanks a lot !!Demurrage
Thanks @sgtpep! This successfully triggers addEventListener('popstate', event)Posehn
G
16

The paragraph you reference is a little ambiguous. Reading the example on the same page, it is clear that popstate is only triggered when the user clicks the back button, not when the script calls pushState().

Georas answered 8/6, 2012 at 10:41 Comment(4)
popstate is also triggered when the user presses the forward button.Inoffensive
pushstate does trigger popstate! Hence "A popstate event is dispatched to the window every time the active history entry changes"!Arteriosclerosis
@AlexGill Do you have a test-case that demonstrates this behavior? Something like: ` window.onpopstate = function(e) { alert('popstate'); } history.pushState(null, ''); `Georas
popstate is also triggered with window.location.hash = "<some new hash>". Dmitri Farkov's answer below mentions this detail and it's important I think.Eucharis
M
14

You are reading MDN's "guide page" which is not meant to be normative.

Consider reading MDN's "documentation page" for WindowEventHandlers.onpopstate instead:

Note that just calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event is only triggered by doing a browser action such as a clicking on the back button (or calling history.back() in JavaScript). And the event is only triggered when the user navigates between two history entries for the same document.

Another undocumented way of triggering popstate is by direct manipulation of the window.location object.

// this also triggers popstate 
window.location.hash = "#some-new-hash"
Minutely answered 10/10, 2014 at 21:48 Comment(3)
This should be the accepted answer because of the window.location.hash thingEucharis
No state will be passed in this way, it's only good for a stateless operationMicronucleus
Another good explanation of how the event works can be found here codeguage.com/courses/js/events-popstate-eventDesegregate
E
2

My solution:

var url = "http://awesome.website.net/route/to/paradise";
window.history.pushState({}, "", url);
window.history.pushState({}, "", url); // yes twice
window.history.back();

It will trigger a soft-navigation via 'popstate' event and no HTTP request.

Emlin answered 14/9, 2014 at 3:37 Comment(2)
Is this what all of the front-end frameworks do, too?Underpin
That sucks, because you end up with redundant forward state. No, frameworks don't do that. They just have good code that calls the same callback on both popstate and after pushState.Swink
S
0

Document https://developer.mozilla.org/en-US/docs/Web/Events/popstate says:

Note that just calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event will been triggered by doing a browser action such as a click on the back or forward button (or calling history.back() or history.forward() in JavaScript).

St answered 9/2, 2017 at 6:36 Comment(0)
B
-1

I ran into this too... I think the event only fires if you have something at the top level of your data object that is distinct from the previous state.

Try this:

var data = {rand: Math.random()};
window.history.pushState(data, '', '/foo');
Banquet answered 13/9, 2012 at 17:59 Comment(1)
This doesn't call popstate either. At least not on Firefox 26.Inoffensive

© 2022 - 2024 — McMap. All rights reserved.