Correctly handling the BFCache in react - javascript

I'm showing a loading screen (state) before redirecting to an external url (payment provider), since they tend to load for a while.
If the user chooses not to complete the payment and goes history.back() (Gesture, back button, ...) the browser pulls the page before from the BFCache, including the loading state, and the user will be "stuck" loading forever.
How would you suggest handling that? Persisted loads can be detected using the pageshow event, but I'm not sure if that is the react way to handle the case.

Persisted loads should be handled manually. In your case you should handle the
loader state based on the event property persisted from pageshow event handler.

Related

trigger unload event in iframe app when parent application tab closes

I have two apps, App1 and App2.
App2 is embedded as an iframe in App1, so App1 is parent app which embeds App2.
When user closes App1 from browser, I want to trigger an api in App2.
I tried using 'unload' event in App2, but that is not getting triggered when App2 closes (am checking by putting debugger point on event listener function, which gets called when standalone App2 gets closed).
Is there a way to accomplish this? Thanks
Historically trying to make asynchronous requests in unload events has never been reliable
For that reason navigator.sendBeacon(url, data) was created.
It works in the background even after page or tab is gone and helps solve a lot of the reliability problems of using unload events.
With the sendBeacon() method, the data is transmitted asynchronously when the User Agent has an opportunity to do so, without delaying unload or the next navigation.
I've never used it in the disappearing iframe scenario like yours but believe it would solve your issue

Prevent 'beforeunload' event being fired on window.location

I have an analytics service which uses
window.addEventListener('beforeunload', endSession);
to record the user navigating away from the app.
In another part of the app we have downloading functionality, using
window.location = urlOfItemToDownload;
This causes the beforeunload event to trigger, which is undesirable.
There are many downloads in the app so toggling a boolean variable isnt so scalable. Is there any way around it?

Chrome: disable pre-render of hash change

We're developing a web application that handles state change via change of the hash of the page (e.g. example.com/#/page1).
Lately, I've been running into an issue with Google Chrome, when the prefetch option is enabled ("Predict network actions to improve page load performance"). Among the different routes, we have #/logout that performs the logout.
In the "normal" state, I'm on the page example.com/#/ (the main page), and as I start typing "l" after that (example.com/#/l), Chrome autocompletes with logout. However, not only it does autocomplete, but it also calls the "haschange" event, so the client is sending a request to log out to the server... Even just by typing a l!
This behaviour is not only unexpected, but it's also dangerous. Aside from unchecking "Predict network actions to improve page load performance" in the settings page (which is on by default), is there a way to prevent Chrome to do this?
EDIT
A small new "discovery". Actually, Chrome is not firing the "hashchange" event, as a console.log in the event handler is not being executed. Chrome learnt that, when visiting the #/logout page, a request to the server (GET /auth/destroy) is called, and so it's firing it by itself! What can we do to stop this?
Answering my own question. This is not really a solution, but rather a workaround.
According to this documentation, prendering is disabled in certain situations: with POST requests (not an option in our case) and when the resources are served via HTTPS.
Since we were already going to enable HTTPS in the production environment, we just enabled it in the development one as well and the issue disappeared. However, I still feel like this is more of a workaround than a real solution.

pushState: How to prevent browser from attempting to load the page

I am trying to get a hook into the history object. Lets say http://my-site.com is the root url. If someone enters http://my-site.com/<url-fragment> is it possible to listen to the change of the fragment and fire and event associated with that in Javascript?
No.
You can use a beforeunload event to recognise that the page is being left, but you can't find out where it is going to.
You have to wait for the browser to load the new page and then deliver it from the server (well, you could load the homepage then use JavaScript to read location.href, but that would defeat the point of using the history API).

Ajax, back button and DOM updates

If javascript modifies DOM in page A, user navigates to page B and then hits back button to get back to the page A. All modifications to DOM of page A are lost and user is presented with version that was originally retrieved from the server.
It works that way on stackoverflow, reddit and many other popular websites. (try to add test comment to this question, then navigate to different page and hit back button to come back - your comment will be "gone")
This makes sense, yet some websites (apple.com, basecamphq.com etc) are somehow forcing browser to serve user the latest state of the page. (go to http://www.apple.com/ca/search/?q=ipod, click on say Downloads link at the top and then click back button - all DOM updates will be preserved)
where is the inconsistency coming from?
One answer: Among other things, unload events cause the back/forward cache to be invalidated.
Some browsers store the current state of the entire web page in the so-called "bfcache" or "page cache". This allows them to re-render the page very quickly when navigating via the back and forward buttons, and preserves the state of the DOM and all JavaScript variables. However, when a page contains onunload events, those events could potentially put the page into a non-functional state, and so the page is not stored in the bfcache and must be reloaded (but may be loaded from the standard cache) and re-rendered from scratch, including running all onload handlers. When returning to a page via the bfcache, the DOM is kept in its previous state, without needing to fire onload handlers (because the page is already loaded).
Note that the behavior of the bfcache is different from the standard browser cache with regards to Cache-Control and other HTTP headers. In many cases, browsers will cache a page in the bfcache even if it would not otherwise store it in the standard cache.
jQuery automatically attaches an unload event to the window, so unfortunately using jQuery will disqualify your page from being stored in the bfcache for DOM preservation and quick back/forward. [Update: this has been fixed in jQuery 1.4 so that it only applies to IE]
Information about the Firefox bfcache
Information about the Safari Page Cache and possible future changes to how unload events work
Opera uses fast history navigation
Chrome doesn't have a page cache ([1], [2])
Pages for playing with DOM manipulations and the bfcache:
This page will be stored in the regular cache
This page will not, but will still be bfcached
I've been trying to get Chrome to behave like Safari does, and the only way I've found that works is to set Cache-control: no-store in the headers. This forces the browser to re-fetch the page from the server when the user presses the back button. Not ideal, but better than being shown an out-of-date page.
Facebook remembers page state by modifying the hash identifier in the URL for ajax requests. These changes are recorded in browser history, so when the user clicks the back button, the hash changes to what it was before. So then it is implied that you will need some Javascript to monitor the has identifier and react when it is changed by the browser. Andreas Blixt has a hash monitoring script available.
This has nothing to do with the hash (#) symbol.
If you would check apple's HTTP headers, it's simply caching the page.
Using the URL hash/fragment identifier is a pretty common way to hook/remember state in a web application that relies on Ajax and DOM updates.
Check out the Really Simple History project for some ideas. It's possible to monitor the URL for changes to the hash, and rsh does this, taking into account browser differences.
For anybody running in problems with Rails and this -- your issue isn't bfcache (I thought it was) -- it's the turbolinks gem. Here is how to remove it.
Hopefully this'll save you some time and banging your head against the wall.
What you are looking for is for some type of URL hash management. The # in the url is for client side only.
When you change the state of the back with JS, then you update the data in the # of the url.
Also you add some type of polling that monitors if the hash has changed, and loads the state of the page based off the new data in the hash.
Take a look at this:
http://ajaxpatterns.org/Unique_URLs

Categories