T
TanStack13mo ago
equal-aqua

I don't know if I'm misunderstanding streaming?

(I'm using next.js 14 app router) So I'm just trying to experiment around, and I can't really get streaming to work, like Suspsense. It just never says Loading... This is my page.tsx:
export default function StreamingTestQuery() {
const queryClient = getQueryClient();

void queryClient.prefetchQuery<PlayerCountType[]>({
queryKey: ["playerCount"],
queryFn: () => getPlayerCount(),
});

return (
<div>
<h1>Streaming Test with React Query</h1>
<HydrationBoundary state={dehydrate(queryClient)}>
<PostFeedQuery />
</HydrationBoundary>
</div>
);
}
export default function StreamingTestQuery() {
const queryClient = getQueryClient();

void queryClient.prefetchQuery<PlayerCountType[]>({
queryKey: ["playerCount"],
queryFn: () => getPlayerCount(),
});

return (
<div>
<h1>Streaming Test with React Query</h1>
<HydrationBoundary state={dehydrate(queryClient)}>
<PostFeedQuery />
</HydrationBoundary>
</div>
);
}
And from what i could understand, this should render instantly, since there's no async work, and the promise gets put into the QueryCache. But it dosen't render instantly. This is PostFeedQuery.tsx:
const PostFeed: FC<PostFeedProps> = ({}) => {
const { data: playerCount, isLoading } = useSuspenseQuery({
queryKey: ["playerCount"],
queryFn: () => getPlayerCount(),
});

console.log(isLoading); // Always false
if (isLoading) {
return <div>Loading...</div>;
}
const PostFeed: FC<PostFeedProps> = ({}) => {
const { data: playerCount, isLoading } = useSuspenseQuery({
queryKey: ["playerCount"],
queryFn: () => getPlayerCount(),
});

console.log(isLoading); // Always false
if (isLoading) {
return <div>Loading...</div>;
}
7 Replies
equal-aqua
equal-aquaOP13mo ago
Hope someone could explain a bit further
conscious-sapphire
conscious-sapphire13mo ago
because with suspense, isLoading is always false because it will bubble up to the nearest suspense boundary Wrap your component in a suspense boundary or create a loading.tsx or something like that so next creates one for you the point of suspense is (in part) that you don't have to write if loading and if error checks anymore
equal-aqua
equal-aquaOP13mo ago
So isLoading would never really be used with useSuspenseQuery? This seems to work, don't know if you meant this:
return (
<div>
<h1>Streaming Test with React Query</h1>
<Suspense fallback={<p>Loading...</p>}>
<HydrationBoundary state={dehydrate(queryClient)}>
<PostFeedQuery />
</HydrationBoundary>
</Suspense>
</div>
);
return (
<div>
<h1>Streaming Test with React Query</h1>
<Suspense fallback={<p>Loading...</p>}>
<HydrationBoundary state={dehydrate(queryClient)}>
<PostFeedQuery />
</HydrationBoundary>
</Suspense>
</div>
);
conscious-sapphire
conscious-sapphire13mo ago
yes
equal-aqua
equal-aquaOP13mo ago
I'm pretty new to TanStack Query, but what would be the point of using it, in this scenario. Couldn't you just pass the data down? Does it have to do with error handling, cache, or other functionality that's under the hood?
modern-teal
modern-teal13mo ago
you can just pass the data down, but by using useSuspenseQuery, your component can focus on rendering the success state of your data-fetching. Then you have the Suspense react primitive to handle the loading state and an ErrorBoundary component to handle the error state
equal-aqua
equal-aquaOP13mo ago
I don't really understand that. If I pass it down, then the component will already have the data, and would focus on rendering the success state as much as useSuspenseQuery. Or? I just saw there was the experimental ReactQueryStreamedHydration, and by my undestanding, I will just be able to remove all of my prefetching, and it will still fetch it on the server. Am I understanding it correctly?

Did you find this page helpful?