-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there any way to have the back button load just a cached page? #7936
Comments
Also from what I can tell, this has been an issue with Remix from the start. I don't really have experience with Next.js, so I'm not sure if this is the norm with all universal-rendered frameworks that hydrate the client after first load, but I have a hunch that it is the norm. Can this problem even be solved? |
This looks like it might have something to do with https://twitter.com/dan_abramov/status/1568219286744797190 Anyone want to take a stab at a fix for this and see if the same thing works for https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/index.tsx#L1627 |
huh interesting. i'll try to give this a shot on my site. FWIW though, a lot of those examples I hadn't scrolled yet e: i can also replicate on iOS chrome as well |
From my experience, it's happening only when client side logic receives new information from loader and forces history DOM to re-render and re-calculate. This is not the case, when your route's view is persistent or it's height stays the same as it is on history. When your first render (SSR) page looks the same as it is after first CSR will be applied, you will not see the jumping effect. This flashing and jumpy effect can be avoided. It just requires a bit to think through the archidecture and rendering logic. Popular thing is to render Challenging topic is to avoid jumping effect on infinity pagination. There are loads of material about it on Google however and it isn't Remix issue, it's actually classical infinity pagination issue. That's why Facebook never destroy it's timeline from DOM when you navigate to another page. About the ScrollRestoration of Remix - it's actually A+ grade component from my experience. About 1.5 year ago I used next.js on my projects and their ScrollRestoration was very chaotic and unpredictable back then. Not sure, if they have improved it by now. Only case when revalidation of loaders during navigation on browser history stack causes the problem, is the case when entities sort order has changed (ie. new entity has been added or some entity has been resorted). It doesn't cause jumpy effect, it just replaces history elements with new sort order. I don't think that's expected UX behaviour. Users, who using browser navigation, usually expect to continue browsing where they left off. So maybe this side-effect worths a discussion to add an option to opt-out from revalidation during the browser history navigation? |
On iOS safari, if you visit next.js's documentation site, which is built upon nextjs itself, try to scroll back, you will have similar flashing issue. I think this might be a case in which safari does not behave well. No problems on chrome. |
There in fact two problems during iOS swipe back action:
For problem 1, I'm not sure with the reason why a grey background shows. It seems this is the behavior if safari sees For problem 2, for the current Remix which does not cache the data of |
just so it's on the record (and i haven't attempted the hack/fix yet), i can absolutely reproduce this on mobile chrome as well just want this made aware before we write this off as a safari-only bug: trim.BB7CDD53-421C-4F02-89A7-48BC769396CF.MOVi feel like there's 2 different issues here
|
@martinmckenna I can reproduce issue on datagunung.com, however I am not able to reproduce issue on remix.run, shopify.com and on my projects. I digged deeper and I can confirm datagunung have standard issue with infinity pagination which causes re-renders and blinking during back/forward navigation. You can read more about that on comment above. Delay during back/forward navigation is caused by revalidation, which is different issue and discussion. It requires storing each state of the page to local_storage or session_storage to offer option to disable revalidation during browser history navigation. Currently, Remix do not save those states and that's why revalidation is required. |
Hi @martinmckenna, I'm the maintainer of datagunung.com. Have you got a chance to test this back button behavior in Android? Here is one example that I was able to capture: or |
@r0stiars0 just iOS safari and chrome so far. it's not a problem on non-mobile, so i'm not surprised that Android doesn't have this issue. |
@brophdawg11 so I FINALLY got around to trying out Dan's code and it seems to solve the blank page issue, but doesn't solve the issue of the "flashing the previous content" I updated this code in my react-router-dom node_modules: // Trigger manual scroll restoration while we're active
React.useEffect(() => {
window.history.scrollRestoration = "manual";
return () => {
window.history.scrollRestoration = "auto";
};
}, []); to this: React.useEffect(() => {
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
if (isSafari) {
// This is kind of a lie.
// We still rely on the manual Next.js scrollRestoration logic.
// However, we *also* don't want Safari grey screen during the back swipe gesture.
// Seems like it doesn't hurt to enable auto restore *and* Next.js logic at the same time.
history.scrollRestoration = 'auto';
} else {
// For other browsers, let Next.js set scrollRestoration to 'manual'.
// It seems to work better for Chrome and Firefox which don't animate the back swipe.
window.history.scrollRestoration = "manual";
}
}, []); I also tried without the cleanup function, but the issue still remains. So as suspected, we have 2 bugs here, not 1. |
i was doing some googling yesterday too and found some similar conversations about the page flashing happening in Svelekit, Nuxt, and Next: |
@brophdawg11 wondering if you had any thoughts on the above ^^ should the hacky fix be PRed here even if it doesn't solve the flickering issue? |
To prevent white background instead of previous / forward page's preview during the half a drag on Safari, the scrollRestoration auto hack seem to prevent that. However, it brings in visually more annoying feature - visual scroll jump. That's due to nature of "manual" and "auto" scrollRestoration behaviour. I haven't seen any iOS user to use prev/forward actions to just preview the previous page on half screen. User goes back to navigate the last page where they left off. Considering that case scenario, white preview is less annoying than slower and jumpy previous page due to triple browser calcuations due to scrollPosition. White preview is something that iOS Safari developers can resolve if needed since it's not React, react-router (Remix), next.js problem - it's CSR problem. CSR happens with any SSR javascript framework which uses re-hydration / VirtualDOM (React, Angluar, Vue, ..). All the other behaviours are logical - javascript will update your data on mount. During prev/scroll your view mounts and triggers data revalidation and all the other application specific mounting actions. What Gemini thinks about the issue?Understanding the Issue: iOS Safari, Scroll Restoration, and Drag PreviewProblem: Potential Causes:
Additional Considerations:
It's worth to report the issue to Apple via Apple Feedback Assistant rather than working out temporary hack, which will prevent Apple to resolve the main issue and putting Safari to same path where Internet Explorer was. |
gonna post the react-router issues regarding the same bugs here too just for visibility: |
Since this issue has been open for 1 year, may I assume Remix hasn't considered caching since day 0 thus is broken by design? |
perhaps it would be a nice idea to just be able to turn off client-side routing altogether |
You can use |
@mikkpokk lol good call, i'm dumb 😅 |
What version of Remix are you using?
2.0.1
Are all your remix dependencies & dev-dependencies using the same version?
Steps to Reproduce
I was observing my own site and a few sites in the Who's using remix in production discussion and it seems like out-of-the-box, Remix has this issue with the back button on mobile browsers where the back button doesn't really perform like you'd expect it to. It seems like by default, the page's loader is always re-run and you end up with this really janky experience:
Here's like 4 different examples I found pretty easily just by browsing through that discussion:
video of https://datagunung.com
https://imgur.com/aPe9TiN
video of https://hub.findkit.com
https://imgur.com/50NHxCH
video of https://basementcommunity.com
https://imgur.com/xruVJnD
video of https://ajourney.io
https://imgur.com/5vmVsaO
Now, from what I can tell, HTTP Cache control headers don't really solve this problem. I tried implementing them on both the document and each loader individually, and it seems like this issue still happens. I'm not sure if this is just a side-effect of using client-side hydration after the first render, or perhaps a side-effect of having markup that is generated at the time the page is requested, but I feel like getting a cached page when hitting the back button should be behavior default to Remix without the developer having to figure this out.
Expected Behavior
Page flashes old content before showing right content when hitting back button on mobile browsers
Actual Behavior
Page loads cached page with no flashing on mobile browsers
The text was updated successfully, but these errors were encountered: