Flash of Previous Page When Backswiping / Clicking Back Button on Mobile
Reproduction
TL:DR Here's the runnable example: https://codeberg.org/martinmckenna/react-router-flash-loader-test
and a video of that test application ^^ https://i.imgur.com/qlSmXqZ.mp4
I'm copying over this issue from Remix: https://github.com/remix-run/remix/issues/7936, which I created under a bit of a misnomer.
This issue is with most SSR frameworks. Here's a couple other similar issues in other SSR framework repos:
https://github.com/sveltejs/kit/issues/10700 https://github.com/vercel/next.js/issues/57243 https://github.com/nuxt/nuxt/issues/6101
The issue here is that when backswiping or clicking the back button on mobile, the old content flashes before the loader gets a chance to re-run and load the "previous" but really "new" content.
This PR in react.dev was proposed as a solution, but does not solve the problem:
https://github.com/reactjs/react.dev/pull/5029
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, both Remix and now React Router have this issue:
- Navigate to new page
- Swipe to go back (or hit back button)
- See flash of the latest page you were on, then the page you expect to see appears
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
System Info
System:
OS: macOS 15.6
CPU: (14) arm64 Apple M3 Max
Memory: 441.38 MB / 36.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.19.4 - ~/.nvm/versions/node/v20.19.4/bin/node
Yarn: 1.22.22 - /opt/homebrew/bin/yarn
npm: 10.8.2 - ~/.nvm/versions/node/v20.19.4/bin/npm
Browsers:
Brave Browser: 139.1.81.131
Chrome: 139.0.7258.67
Safari: 18.6
npmPackages:
@react-router/dev: 7.7.0-pre.0 => 7.7.0-pre.0
@react-router/fs-routes: 7.7.0-pre.0 => 7.7.0-pre.0
@react-router/node: 7.7.0-pre.0 => 7.7.0-pre.0
@react-router/serve: 7.7.0-pre.0 => 7.7.0-pre.0
react-router: 7.7.0-pre.0 => 7.7.0-pre.0
vite: 7.0.4 => 7.0.4
Used Package Manager
yarn
Expected Behavior
When I click browser back button / backswipe, the old content doesn't flash
Actual Behavior
When you go to a page, then backswipe or click back, the previous page flashes before showing the new page
@kalnode posted about a library that potentially solves this issue by caching loader data:
https://github.com/remix-run/remix/issues/7936#issuecomment-2912537643
To align with our new Open Governance model, we are now requiring that all issues have a minimal and runnable reproduction. This should help us to focus on actionable issues and be more responsive to newly filed issues.
To get this re-opened, please add a reproduction to the Issue description and tag @brophdawg11 or @brookslybrand in a comment so we can re-open.
Or, if this was closed by mistake and there is a valid reproduction, please ensure that it is linked in the Issue description and and tag @brophdawg11 or @brookslybrand in a comment so we can re-open.
If you have any questions, you can always reach out on Discord. Thanks again for providing feedback and helping us make React Router even better!
@brophdawg11 @brookslybrand updated the OP with a runnable thing, pls re-open
same issue here, very annoying user experience on iOS
Is there an actual browser-level solution to this? This is due to the BFCache, right? It looks like none of the above linked issues for the other framework have been resolved either, so does it still exist for all client-side-routed frameworks?
I found that using https://github.com/forge-42/remix-client-cache kinda-sorta fixes the issue, but not quite.
Most of my pages don't flash when i cache them using this library, but the issue still persists on pages with a larger amount of markup (and I'm not talking a crazy amount of markup, but just pages that have more images than average). I had a bunch of small icons on 1 page and swiping back still causes the flash, so it's not perfect.
But I would still recommend people with this issue give remix-client-cache a try
You can workaround the issue by using a simple css opacity transition and a loading overlay in your page Layout for a better user experience:
export function PageLayout({
const navigation = useNavigation();
...
<div
className={`transition-opacity duration-300 ${
navigation.state === 'loading' ? 'opacity-0' : 'opacity-100'
}`}
>
{children}
</div>`
here is how it solves the issues: 1 user navigates from A to B 2 user swipes back to b: browser show page A, navigation starts, problem DOM of B is still loaded 3 page A loads anew. The flicker is cause by 2, but using navigation state, you can change the opacity of the DOM (of B) while page A is still loading.
I don't think it's a bug tbh. But I can image react-router providing an API to support this transition between children during navigation (although with a simple workaround like this one, adding support in the library is maybe an overkill).