router icon indicating copy to clipboard operation
router copied to clipboard

Pending component doesn't work on root route

Open geoff-harper opened this issue 1 year ago • 8 comments

Which project does this relate to?

Router

Describe the bug

I've noticed the pending component doesn't stay mounted if it's on the __root route. It seems like it does quickly render but doesn't stay until the __root loader method is finished, instead it instantly unmounts

Your Example Website or App

https://codesandbox.io/p/devbox/epic-shape-z676nh

Steps to Reproduce the Bug or Issue

  1. Verify that you see a green box on first load to verify that non __root pending component works
  2. Go to src\routes\index.tsx and comment out the pending component and loader
  3. Go to src\routes\__root.tsx and uncomment the same code from previous file
  4. Verify that the green box does not appear after refreshing window

Expected behavior

I expect to see the green box upon loading after the 4th repro step. I've left a red box as the router's default pending component to show that does seem to be working normally in all relevant cases

Screenshots or Videos

No response

Platform

  • Version: 1.57.8

Additional context

No response

geoff-harper avatar Sep 10 '24 20:09 geoff-harper

Would it be possible to get an update/acknowledgement for this one? The users yearn for loading spinners

geoff-harper avatar Nov 19 '24 14:11 geoff-harper

looking into this right now, I don't see any pending component, also not in the code. maybe the code sandbox is not saved correctly? can you please provide the reproducer on stackblitz (it's nicer to work with)?

schiller-manuel avatar Nov 19 '24 20:11 schiller-manuel

@geoff-harper the shared sandbox doesn’t look at all how you’ve described in the steps to reproduce. That makes it really hard for us to look into...

TkDodo avatar Nov 23 '24 10:11 TkDodo

I stumbled upon the same problem. Please see this reproduction: https://stackblitz.com/edit/sb1-8emvur?file=src%2Froutes%2F__root.tsx

I am not sure about the mounting and unmounting in the original issue, but this one shows that the pendingComponent is not rendered either for beforeLoad or loaders in the createRootRoute.

PhilGarb avatar Nov 24 '24 09:11 PhilGarb

Apologies for the delay, I was out of the country. @PhilGarb's repro looks like what I am experiencing, thank you for making it

geoff-harper avatar Nov 26 '24 14:11 geoff-harper

Also seeing the same issue when using a beforeLoad in the root route. The only way I can get a pending component to show is if it is set as the defaultPendingComponent in the router options, but that's not quite what I want.

Looks like you can force it using wrapInSuspense - https://github.com/TanStack/router/issues/2182#issuecomment-2495539306

jameshoward avatar Dec 02 '24 16:12 jameshoward

I've made a new repro on stackblitz

You can try different combos on pending component and/or loaders on root and file routes, but the main case is everything uncommented and neither pending component rendering. The other route is the index route.

After another look I do actually see the index's red pending component flash quickly

geoff-harper-qii avatar Jan 02 '25 22:01 geoff-harper-qii

This drove me nuts for about an hour. Following as I either get a flash of the pending component or a white page.

rostero1 avatar Jun 13 '25 12:06 rostero1

I also drive into this with autoCodeSplitting: true. My index.html has a basic skeleton UI included and should be visible until the authentication is done and the routes are fully loaded. With react-router and hydrateFallbackElement this is no problem. But with @tanstack/router I get short white flickers: Skeleton UI > White flicker > Real UI

I improved this by

export const Route = createRootRoute({
  component: RootLayout,
  staticData: {
    brotkrume: <Brotkrume titel='titel' path={PATH_ROOT} />
  },
  // without loader and wrapInSuspense, pendingComponent never get's rendered
  loader: () => new Promise<object>((resolve) => setTimeout(() => resolve({}), 0)),
  pendingComponent: SplashScreen,
  pendingMs: 0,
  pendingMinMs: 0,
  wrapInSuspense: true
})

now there seems to be only one single frame of white (no DOM content). Thats maybe because the wrapped Suspense has no fallback attribute.

codeart1st avatar Sep 25 '25 09:09 codeart1st

I can confirm that in the RC even with the bellow added the pending component does not show when using beforeLoad, It seems to always fall back to the defaultPendingComponent, disregarding the provided pending component

        pendingComponent: customPendingComponent,
	pendingMs: 0,
	pendingMinMs: 0,
	wrapInSuspense: true,

jacobgad avatar Oct 03 '25 12:10 jacobgad

I can also confirm that it is always defaulting to the defaultPendingComponent as well. Has anyone found a way around this?

Jonathanvwersch avatar Oct 14 '25 15:10 Jonathanvwersch

Confirming it works now, except a few frames where previous content is removed an pendingComponent not mounted. This is a short white (body background) flicker. pendingMs: 0 & pendingComponent on root route.

Image

codeart1st avatar Oct 18 '25 12:10 codeart1st