T
TanStack•3mo ago
extended-salmon

Start + useQuery prefetch question

Hi! I was under the impression that with react-router-with-query, we'd be able to start a query on the server and continue it on the client with useQuery, even when the query doesn't fully resolve inside the loader - essentially continue the query where the server left off. I'm wondering if that is actually the case or if that is only possible with useSuspenseQuery. In the example below, without any nested components, our query takes two seconds to resolve. If we prefetch inside the loader (without awaiting the prefetch or any subsequent duration), we will get data (1) from useQuery - the query runs fully in the client. When the loader is longer and allows for the query to fully resolve in the server, we get data (2), fetched in the server.
// server logs
// server prefetch ini 2025-06-29T15:18:37.162Z
// server prefetch end 2025-06-29T15:18:39.163Z

// (1) useQuery client data
// timestamps post-server loader logs
// {
// "message": "Hello from the server",
// "ini": "2025-06-29T15:21:01.082Z",
// "end": "2025-06-29T15:21:03.084Z"
// }

// (2) useQuery client data, when query resolves inside loader
// timestamps match the initial prefetch server logs
// {
// "message": "Hello from the server",
// "ini": "2025-06-29T15:18:37.162Z",
// "end": "2025-06-29T15:18:39.163Z"
// }
// server logs
// server prefetch ini 2025-06-29T15:18:37.162Z
// server prefetch end 2025-06-29T15:18:39.163Z

// (1) useQuery client data
// timestamps post-server loader logs
// {
// "message": "Hello from the server",
// "ini": "2025-06-29T15:21:01.082Z",
// "end": "2025-06-29T15:21:03.084Z"
// }

// (2) useQuery client data, when query resolves inside loader
// timestamps match the initial prefetch server logs
// {
// "message": "Hello from the server",
// "ini": "2025-06-29T15:18:37.162Z",
// "end": "2025-06-29T15:18:39.163Z"
// }
useSuspenseQuery will work and initially render the data (2), prefetched in the server, but will then immediately start refetching in the client when the component renders and replace it - which we tried to prevent unsuccessfuly with various combinations of route and queryClient staleTime.
11 Replies
extended-salmon
extended-salmonOP•3mo ago
const serverFn = createServerFn().handler(async () => {
const ini = new Date();
await new Promise((resolve) => setTimeout(resolve, 2000));
return { message: "Hello from the server", ini, end: new Date() };
});

const serverQueryOptions = () =>
queryOptions({
queryKey: ["server"],
queryFn: serverFn,
staleTime: 10_000
});

export const Route = createFileRoute("/")({
loader: async ({context}) => {
console.log('Server prefetch ini', new Date())
context.queryClient.prefetchQuery(serverQueryOptions()).then(() => console.log('Server prefetch end', new Date()))
// await new Promise((resolve) => setTimeout(resolve, 2000))
},
// staleTime: 10_000,
component: IndexPage
})
const serverFn = createServerFn().handler(async () => {
const ini = new Date();
await new Promise((resolve) => setTimeout(resolve, 2000));
return { message: "Hello from the server", ini, end: new Date() };
});

const serverQueryOptions = () =>
queryOptions({
queryKey: ["server"],
queryFn: serverFn,
staleTime: 10_000
});

export const Route = createFileRoute("/")({
loader: async ({context}) => {
console.log('Server prefetch ini', new Date())
context.queryClient.prefetchQuery(serverQueryOptions()).then(() => console.log('Server prefetch end', new Date()))
// await new Promise((resolve) => setTimeout(resolve, 2000))
},
// staleTime: 10_000,
component: IndexPage
})
evident-indigo
evident-indigo•3mo ago
there is a sync issue still in the library. it will soon be resolved when we migrate to seroval serializer
dependent-tan
dependent-tan•3mo ago
evident-indigo
evident-indigo•3mo ago
don't think so. the sync issue affects promise streaming especially for useSuspenseQuery
extended-salmon
extended-salmonOP•3mo ago
Good to know, thanks for the fast reply! I suppose this affects both the useQuery and useSuspenseQuery approaches?
evident-indigo
evident-indigo•3mo ago
no only useSuspenseQuery if you do not await a query in the loader it won't be streamed right now only if awaited or accessed via useSuspenseQuery we might be able to stream non awaited queries in the future
extended-salmon
extended-salmonOP•3mo ago
Yeah, this is what I was expecting - I think it'd be a great addition. And I think this would be a good add to the docs as well
evident-indigo
evident-indigo•3mo ago
we dont have docs about the query integration at all right now i guess 😄 so yes, this should all be properly documented
extended-salmon
extended-salmonOP•2mo ago
Awesome, thanks for the input. Looking forward to these changes @Manuel Schiller great job with the seroval integration, amazed by the shipping speed
ambitious-aqua
ambitious-aqua•2mo ago
Could you share the MR?
extended-salmon
extended-salmonOP•2mo ago

Did you find this page helpful?