Chrome popstate not firing on Back Button if no user interaction
Asked Answered
G

2

52

I'm trying to use "pushState" and the "popstate" event to trap Back button navigation, however, while the popstate event triggers correctly in Firefox, it doesn't trigger in Chrome (Version 76.0.3809.87 (Official Build) (64-bit)) if there is no user interaction.

From testing, it looks like the popstate event only gets triggered if the user interacts with the page (ie. clicks somewhere on the document). So if you load the page without interacting and hit Back, the popstate function is not called.

I've added a Fiddle to showcase this: https://jsfiddle.net/0xwvLndu/

To test the Fiddle in Chrome, just click the link and hit the Back button. You'll see no alert. Then click the link again but this time click anywhere on the Fiddle document and then hit the Back button, the alert is then triggered.

I found a discussion on the Chromium forum that may relate to this quirk, and perhaps this has been implemented to prevent abuse of history entries - https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/OCS7g72HtyI and https://github.com/WICG/interventions/issues/21#issuecomment-425609246

If this is the case, does it mean that popstate cannot be relied on anymore to trap Back button actions, and if so, is there a work around solution?

Below is an example of what I've been testing with:

window.addEventListener('load', function() {
    history.pushState(null, null, document.URL);
});

window.addEventListener('popstate', function(event) {
    alert('test');
});

I expected the alert to be triggered on Back Button regardless of user interaction, but this does not happen in Chrome.

Galatea answered 3/8, 2019 at 14:12 Comment(4)
@Drenai Thanks for the feedback. I've edited my question to try make it more specific to the issue at hand. Hopefully that makes it clearer.Galatea
I read more about it at the link below. Seems like Chrome are purposely preventing the hijacking of default back button behaviour (and for good reason). If you find a way around it, I doubt it will be reliable, as future versions of Chrome would likely patch it again nakedsecurity.sophos.com/2019/05/09/…Nosy
@Nosy Thanks for the article - helps confirm the change. I do see the reason for it, although it does mean legitimate use cases no longer work. I guess I will need to look at other ways to achieve what I need (but likely at a cost to user experience).Galatea
I'm so pleased to have come across this question. For the life of me, I could not understand what I was doing wrong for the page to be reloading when I hit Back. Sure enough, once I clicked some spots on my page before hitting Back, everything worked as expected. How bizarre.Unqualified
V
4

Try adding a setTimeout of 0

window.onpopstate = () => setTimeout(alert.bind(window, "Pop"), 0);

When writing functions that process popstate event it is important to take into account that properties like window.location will already reflect the state change (if it affected the current URL), but document might still not. If the goal is to catch the moment when the new document state is already fully in place, a zero-delay setTimeout() method call should be used to effectively put its inner callback function that does the processing at the end of the browser event loop: window.onpopstate = () => setTimeout(doSomeThing, 0);

Content is taken from https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event

On a sidenote it is advised not to use this as browsers may remove this any time.

Vashtee answered 20/1, 2021 at 16:33 Comment(1)
As of writing this comment, it appears that even this does not reliably work in ChromeSubarid
S
3

As others suggested in comment, this should be by design of browser software to prevent hijacking of its default back button behavior.

Stereoscope answered 28/12, 2020 at 9:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.