T
TanStack•16mo ago
noble-gold

Should `prefetchQuery` be await'ed inside the route's `loader`?

I couldn't find any info in the docs specifically about calling queryClient.prefetchQuery inside of a route's loader method. Based on my understanding of both methods, it seems like I would not want to await the prefetchQuery calls since it would block the route from rendering until the query/queries are finished fetching rather than handling the loading state inside the component. For example:
export const Route = createFileRoute('/orders/search')({
component: OrderSearchRoute,
wrapInSuspense: true,
validateSearch: orderSearchFiltersSchema,
beforeLoad: async ({ context, location, search: filters }) => {
return {
optionsQueryOptions: queryOptions({
queryKey: ['order-search-options'],
queryFn: () => getOrderSearchOptions(),
}),
ordersQueryOptions: queryOptions({
queryKey: ['order-search', filters],
queryFn: () => getOrderSearchResults(filters),
placeholderData: keepPreviousData,
}),
};
},
loader: ({ context: { queryClient, ordersQueryOptions, optionsQueryOptions } }) => {
// Should these be await'ed?
void queryClient.prefetchQuery(ordersQueryOptions);
void queryClient.prefetchQuery(optionsQueryOptions);
},
});

function OrderSearchRoute() {
const filters = Route.useSearch();
const { ordersQueryOptions, optionsQueryOptions } = Route.useRouteContext();
const { data: options } = useSuspenseQuery(optionsQueryOptions);
const { data: orders, isLoading } = useQuery(ordersQueryOptions);

return (
<div>
<OrderSearchFilters filters={filters} options={options} />
<OrderSearchResults orders={orders} loading={isLoading} />
</div>
);
}
export const Route = createFileRoute('/orders/search')({
component: OrderSearchRoute,
wrapInSuspense: true,
validateSearch: orderSearchFiltersSchema,
beforeLoad: async ({ context, location, search: filters }) => {
return {
optionsQueryOptions: queryOptions({
queryKey: ['order-search-options'],
queryFn: () => getOrderSearchOptions(),
}),
ordersQueryOptions: queryOptions({
queryKey: ['order-search', filters],
queryFn: () => getOrderSearchResults(filters),
placeholderData: keepPreviousData,
}),
};
},
loader: ({ context: { queryClient, ordersQueryOptions, optionsQueryOptions } }) => {
// Should these be await'ed?
void queryClient.prefetchQuery(ordersQueryOptions);
void queryClient.prefetchQuery(optionsQueryOptions);
},
});

function OrderSearchRoute() {
const filters = Route.useSearch();
const { ordersQueryOptions, optionsQueryOptions } = Route.useRouteContext();
const { data: options } = useSuspenseQuery(optionsQueryOptions);
const { data: orders, isLoading } = useQuery(ordersQueryOptions);

return (
<div>
<OrderSearchFilters filters={filters} options={options} />
<OrderSearchResults orders={orders} loading={isLoading} />
</div>
);
}
4 Replies
fair-rose
fair-rose•16mo ago
you can await the one for useSuspenseQuery and not the other one. yes, a waiting blocks, but so does useSuspenseQuery
noble-gold
noble-goldOP•16mo ago
Ok, that's what I thought. I wasnt sure about the options query (the one I am using suspense with) since I figured that the router could at least render the other matching routes without waiting.
fair-rose
fair-rose•16mo ago
yes it's likely better to not wait for this one
noble-gold
noble-goldOP•16mo ago
Awesome, thanks! Just wanted to verify that I was understanding correctly. 🙂

Did you find this page helpful?