T
TanStack•7mo ago
extended-salmon

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
No description
12 Replies
genetic-orange
genetic-orange•7mo ago
Can't say much except "it should work" Show a failing reproduction please
extended-salmon
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
No description
extended-salmon
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
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
genetic-orange•7mo ago
the failed fetch is a stackblitz issue: https://github.com/TanStack/query/issues/8528
extended-salmon
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 cache
extended-salmon
extended-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-salmon
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.tsx
genetic-orange
genetic-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 there
yes
and if so, how can I define the fallback if i dont use a global loading.tsx
with a Suspense boundary around it!
How can I test (not unit test, i just mean manually) that the promise is being handed to the cache
turn 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-salmon
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
genetic-orange•7mo ago
but I can only get this to work if I wrap the HydrationBoundary in the Suspense
I think this shouldn't matter.
doesnt show any values in the cache until it fully resolves
the entry should be there in a pending state while you're suspending
extended-salmon
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?

Did you find this page helpful?