I add an event lister on beforeunload
as customary in my JS/ReactJS application. The function adds a confirmation dialog depending on an internal unSaved
state.
Everything works fine on Chrome and Firefox (macOS / desktop).
On Safari, however:
- the first time "I make use" of the event handler (I leave the page while
unSaved==true
), it works fine as expected, - yet, in subsequent attempts of leaving the page with
unSaved==true
, Safari does not ask for any confirmation at all. - when I go to a new tab (with the same previous URL), again the first time works, subsequent times do not...
What is weirder: I can see that my added event function is actually being called every time on safari since a test console.log
is indeed being printed every time.
My only possible guess is that Safari is somehow caching my confirmation response for the tab? (?)
Any ideas for how to solve this?
My stack:
Safari: Version 10.0.1 (12602.2.14.0.7)
macOS: 10.12.1 (16B2657)
host: localhost
protocols: tested on both, http and https
More info:
- event
pageshow
has the propertypersisted
always set to false. Therefore, the Page Cache by Safari (BFCache) should not be the cause of the problem.
Problem
Your problem is caused by a browser feature called back-forward cache (BFCache).
It is supposed to save complete state of page when user navigates away. The idea is when user navigates back with back button page can be loaded from cache very quickly.
Chrome and Firefox considers event handlers on
beforeunload
event as a signal to not store page in back-forward cache, but Safari ignores such handlers.Solution
I have found only 1 working solution, but it's a bit imperfect, hacky and ugly.
You can check the persisted property of the
onpageshow
event. It is set to false on initial page load. When page is loaded fromback-forward cache
it is set totrue
.The
onpageshow
event is similar to theonload
event, except that it occurs after theonload
event when the page first loads. Also, theonpageshow
event occurs every time the page is loaded, whereas theonload
event does not occur when the page is loaded from the cache.Important to note:
So, use it on your own responsibility:
Credits
Seems to be Safari's back/forward cache issue. This cache (called also BFCache or Page Cache) stores current state of the entire web-page including JavaScript code state and restores it when user press browser's Back button. You can read about it here. Usually when
beforeunload
is used on loaded web-page browser turns BFCache off. But there may be something in your JavaScript code that stops this behavour. Or maybe you setunSaved state = false
and then it gets cached? Try manually turn off back/forward cache by adding workaround on your page: