pendingComponent, Loader, ensureQueryData — What’s happening with navigation?
Hey! I’m seeing a noticeable delay when navigating between routes that have a loader doing a query prefetch. The route does have a
pendingComponent, but when I click to navigate, the browser immediately updates the URL while the actual screen only switches ~1 second later
Is this expected behavior with the combination of pendingComponent + loader + ensureQueryData? Or does this indicate some issue in my setup?
And if this is the expected flow, is there any recommended approach to make the navigation feel more fluid?
This happens regardless of the ssr setting on the route false, true, or "data-only". The delay is always there. In the video I’m attaching, I’m artificially delaying the query by 6 seconds so the behavior is easier to see
Thanks!
4 Replies
fascinating-indigoOP•2w ago
As an extra data point: I noticed that when navigating for the first time to the specific route I’m showing (the one with the delay), if ssr is set to false, the pendingComponent shows up immediately — which is a great experience.
But if ssr is set to true or "data-only", the entire route blocks until the query finishes, and the pendingComponent never appears right away. This confuses me because, according to the docs, "data-only" should still show the pendingComponent immediately (or at least that’s how I understood it).
xenial-black•2w ago
try setting defaultPendingMs on the router (it defaults to 1000) or pendingMs on the route. i'm seeing this too on a route that takes ~1000ms to load which feels pretty bad. setting it to 250 feels a lot better for me but you'll obviously want to tune it yourself
fascinating-indigoOP•2w ago
I fixed it by removing the await from the query prefetch.
The prefetch still runs, but the route doesn’t wait for the response. Not totally sure if that’s the “right” way to do it, but it works.
One important detail: if the prefetch query throws an error, everything breaks 😅 — you need to add a .catch()
I tried the solution you recommended, and it works great! One thing I learned from this is that I was doing it in a route that’s a layout, and until that promise resolves it won’t render the child routes. Thanks a lot!
xenial-black•2w ago
yeah i ran into that with one of my layouts too. ended up converting any data fetching there to prefetchQuery instead of awaiting ensureQueryData, and having the suspense boundary inside the layout route component. not ideal but it works