Different Suspense behaviour depending on where a user comes from
I have a question about Suspense, that might be more a general React question, but maybe someone has an idea with respect to tanstack Router.
Is it possible to have different Suspense behaviour (different Suspense boundaries), depending on how a user reaches a route?
Example: I have a
Suspense component around Route /a:
When a user opens /a in its browser I want that fallback to be displayed (and that works with the code above.)
But: on another route /b I have a Link to /a. When a user clicks that link, I want the user to stay on /b until /a could completely be rendered (or at least until the "topmost" promise is resolved). I would like to display a loading indicator on /b using MatchRoute or something like this.
Using a MatchRoute in /b works, but the problem is, that from /b's point-of-view, /a is considered to be rendered as soon as the Suspense fallback component ( "wait") kicks in. So I stay on /b only until the fallback component of /a is rendered.
Is there a way to get the behaviour I like to have? (btw I'm pretty sure that in next.js the behaviour is the same)
thanks a ton!5 Replies
like-gold•2y ago
with suspense in react, you would need to wrap the navigation itself into
startTransition. With transitions, the current UI would stay visible until the navigation is complete, and you would know that you are in transition, so you could render something slightly different.
if you integrate with the TanStack Router, you don't need manual suspense boundaries, as the router wraps each route in one. You can set the pendingComponent on your route instead. Also have a look at pendingMs and pendingMinMs options because there are some defaults set that you might want to change. All of this can also be set globally.
navigations like Link or navigate from the router are also integrated with suspense.eastern-cyanOP•2y ago
Thanks for your answer!
But my idea / requirement is, that I want to stay on the current route until the next route is finished, but only when navigating through the app.
So:
- user opens directly
/about in the browser (for example from a bookmark): it should display about pendingComponent
- or user instead opens / in the browser and then clicks on a Link to /about(rendered on the /) route), I want to stay on the / until /about has been finished rendering.
I created an example here: https://stackblitz.com/edit/github-p5wztl?file=src%2Froutes%2Fabout.tsx
In the index route there is a Link wrapped in Supsense that calls /about. That works if I add a pendingComponent to /about. But then I do not stay on / until /about is ready, but only until in /about the fallback component is rendered.
In the docs it says Links starts a Transition so I thought I would stay on the current route but that does not work (when removing the pendingComponent fromabout it gets even worse and I get the error "A component suspended while responding to synchronous input." even I have wrapped my Link with Suspense).Nils Hartmann
StackBlitz
Router Quickstart File Based Example - StackBlitz
Run official live example code for Router Quickstart File Based, created by Tanstack on StackBlitz
like-gold•2y ago
I want to stay on the current route until the next route is finished, but only when navigating through the app.yes, this should work by setting a high
pendingMs so that the transition will always be awaited. There's currently an issue that on first load, pending component should be shown immediately. Right now, it also awaits pendingMs, so you'll get a not so good experience on first loads.
However, this only works when integrating with route loaders. In your example with useSuspenseQuery, it will show the pendingComponent because the router doesn't use react transitions (as I recently learned), but its own transitions. I'm not sure if there is a way to wrap <Link> components in actual useTransition, but it would work with navigate calls if you wrap them.
cc @Tanner Linsley this relates to our discussion from yesterdayeastern-cyanOP•2y ago
Thanks for your response that clarifies a lot.
If I remember correctly in a former Router version, I was able to build my desired behaviour, but probably as you said, I was using a loader back then and not useSuspenseQuery. Will try the
pendingMs and loader approach in the next days, after I have finished a small Next.js thing (already curious how Suspense/Transition will behave in there 😉 )
Anyway: I feel (fear) that Suspense and Transition is quite a complex thing...rival-black•2y ago
We do already wrap navigations in transitions, but those transitions are short circuited by uSES