react-router icon indicating copy to clipboard operation
react-router copied to clipboard

Flash of Previous Page When Backswiping / Clicking Back Button on Mobile

Open martinmckenna opened this issue 5 months ago • 7 comments

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:

  1. Navigate to new page
  2. Swipe to go back (or hit back button)
  3. 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

martinmckenna avatar Aug 07 '25 18:08 martinmckenna

@kalnode posted about a library that potentially solves this issue by caching loader data:

https://github.com/remix-run/remix/issues/7936#issuecomment-2912537643

martinmckenna avatar Aug 07 '25 18:08 martinmckenna

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!

github-actions[bot] avatar Aug 08 '25 14:08 github-actions[bot]

@brophdawg11 @brookslybrand updated the OP with a runnable thing, pls re-open

martinmckenna avatar Aug 13 '25 01:08 martinmckenna

same issue here, very annoying user experience on iOS

Dzinlife avatar Oct 13 '25 10:10 Dzinlife

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?

brophdawg11 avatar Oct 15 '25 19:10 brophdawg11

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

martinmckenna avatar Oct 15 '25 19:10 martinmckenna

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).

iyedb avatar Nov 17 '25 15:11 iyedb