Suspense, HydrationBoundary and Streaming - Examples from Docs
has anyone had much success using the streaming pattern here? https://tanstack.com/query/latest/docs/framework/react/guides/advanced-ssr#streaming-with-server-components - if I add a delay(3000) to the function that is the queryFn I was expecting some sort of suspense to kick in, but instead it just waits the whole 3 seconds before doing anything.
I've updated the dehydrated parts of the queryClient options as per the docs
if I take https://tanstack.com/query/latest/docs/framework/react/examples/nextjs-app-prefetching and add the same delay into the fetching of the pokemon info, it still takes the whole delay to show anything to the FE
If I wrap the whole thing in a suspense, it works, but I am not convinced a promise is now being passed to the cache, as nothing appears in the devtools until it finally finishes fetching
What I am hoping to achieve, is that the fetch has already started on the server side, and is then handed to the FE when the response finishes. Maybe trying to pass these promises over the wire is overkill for what I am hoping to achieve but it seemed really cool so wanted to give it a go

12 Replies
genetic-orange•7mo ago
Can't say much except "it should work"
Show a failing reproduction please
extended-salmonOP•7mo ago
https://stackblitz.com/edit/tanstack-query-exdfyurv?file=app%2Fpokemon.ts
here you go, all I did to the example is add the delay of 3000ms to the fetching of the pokemon
and as you can see
extended-salmonOP•7mo ago
it says 500, but theres something just funky in the stackblitz, it still renders it all etc, i think that is inconsequential
it should work without the suspense boundary around it right? where do I indicate the "pending" state, the example inthe docs isnt particular about where do to that
genetic-orange•7mo ago
it should work without the suspense boundary around it right?I don't see a global
loading.tsx ? That's where next usually has the global suspense boundary around the route
we just throw the promise. the rest is a framework problem 😅genetic-orange•7mo ago
the failed fetch is a stackblitz issue:
https://github.com/TanStack/query/issues/8528
GitHub
server error with nextjs , and hydration in v5 · Issue #8528 · Ta...
Describe the bug server error with nextjs , and hydration in v5 Your minimal, reproducible example https://stackblitz.com/github/tanstack/query/tree/main/examples/react/nextjs-app-prefetching?embed...
extended-salmonOP•7mo ago
Sorry I am misunderstanding something here
My assumptions
1. the prefetch fires from the server side, this uses the same queryKey as the
useSuspenseQuery(), and passes the promise to the FE querycache
2. I can then, inside of a HydrationBoundary, use a Suspense in a client component that needs data from useSuspenseQuery()
3. This way I can have the part of the component, that needs the data, to have a loading state somewhere, but its faster than waiting for the client component to eventually ask for it
2a. I didnt think it was dependany on a loading.tsx route boundary - I want to just have the boundary around part of the page that has a dependency on the data
So is this actually all working, and I just need to have the Suspense wrap what I want to "pend"?
How can I test (not unit test, i just mean manually) that the promise is being handed to the cacheextended-salmonOP•7mo ago
I updated the repro - https://stackblitz.com/edit/tanstack-query-dxhzgbcr?file=app%2Fpokemon-info.tsx - I have put the Suspense where I expect it to be
StackBlitz
Query Nextjs App Prefetching Example (forked) - StackBlitz
Run official live example code for Query Nextjs App Prefetching, created by Tanstack on StackBlitz
extended-salmonOP•7mo ago
Does
useSuspenseQuery mark the whole component as pending until that data is there and if so, how can I define the fallback if i dont use a global loading.tsxgenetic-orange•7mo ago
the assumptions are correct, I fail to understand which problem you are facing? Initially, you said you wanted it "without a separate suspense boundary", but if you do that, you need to have a least a
loading.tsx or a global suspense boundary somewhere. Since we suspend, we need a boundary.
if you want granular boundaries, you have to add <Suspsense> - not sure what the react-query related question around that is.
Does useSuspenseQuery mark the whole component as pending until that data is thereyes
and if so, how can I define the fallback if i dont use a global loading.tsxwith a Suspense boundary around it!
How can I test (not unit test, i just mean manually) that the promise is being handed to the cacheturn on the react-query devtools, see if there is an entry in the client cache and monitor the network tab to see that there is no fetch going out from the client. can't look at stackblitz,again, because it has issues with next and streaming so you won't see if it works there. The promise never reaches the client, see the issue I linked to
extended-salmonOP•7mo ago
So maybe this is working exactly as expected?
I thought the
<Suspense> would be inside the HydrationBoundary, but I can only get this to work if I wrap the HydrationBoundary in the Suspense
Positive news is that there is no request from the client to the server for the data that is suspended/prefetch
However the react-query devtools doesnt show any values in the cache until it fully resolves - is that correct or should I see a pending promise in there while it resolves?genetic-orange•7mo ago
but I can only get this to work if I wrap the HydrationBoundary in the SuspenseI think this shouldn't matter.
doesnt show any values in the cache until it fully resolvesthe entry should be there in a pending state while you're suspending
extended-salmonOP•7mo ago
yeah - what I fear is happening, is that its just a normal suspense wrapped call, and the fact that the promise hasnt resolved, isnt being passed down
do you have a repo/example with it working AND it shows in the devtools as it pends?