T
TanStack2y ago
extended-salmon

Loader not waiting for all async operations

When I await multiple promises in a loader function, the page gets rendered as soon as I hit the first await. Example:
export const Route = createFileRoute('/test')({
component: Component,
loader: async ({ context: { queryClient, client } }) => {
const a = await queryClient.ensureQueryData(getData1());
console.log('first');

const b = await queryClient.ensureQueryData(getData2());
console.log('second');

return Promise.resolve([a, b]);
},
});

function Component() {
console.log('render');
const { client, queryClient } = Route.useRouteContext();
const [{ data }] = useSuspenseQueries({ queries: [d()] });
const navigate = useNavigate();

return (
<div>
Test
</div>
);
}
export const Route = createFileRoute('/test')({
component: Component,
loader: async ({ context: { queryClient, client } }) => {
const a = await queryClient.ensureQueryData(getData1());
console.log('first');

const b = await queryClient.ensureQueryData(getData2());
console.log('second');

return Promise.resolve([a, b]);
},
});

function Component() {
console.log('render');
const { client, queryClient } = Route.useRouteContext();
const [{ data }] = useSuspenseQueries({ queries: [d()] });
const navigate = useNavigate();

return (
<div>
Test
</div>
);
}
This will print:
first
render
second
first
render
second
Seems like the router starts rendering as soon as the loader function relinquishes the thread. Am I missing something?
15 Replies
fair-rose
fair-rose2y ago
Is it consistently one second into the loader?
extended-salmon
extended-salmonOP2y ago
A lot quicker than that. It takes 4ms from when the loader function starts until ender is called
fair-rose
fair-rose2y ago
Do you have any pendingMs settings set on the router?
extended-salmon
extended-salmonOP2y ago
No, should I specify one? (note, seems someone else has the same/similar issue: https://github.com/TanStack/router/issues/1168) Tried adding pendingMs to the route, didn't seem to have an effect
fair-rose
fair-rose2y ago
If you add a pending component, does the pending component show?
extended-salmon
extended-salmonOP2y ago
Hmm, I added a pending component and just noticed something. The first time I enter the route it works as expected, as in the pending component shows and then when everything is loaded it renders the real component But if I go back and enter the route a second time, the pending component doesn't show and the real component is rendered immediatly
fair-rose
fair-rose2y ago
Is data there when it renders? Ensure query data won’t await if there is stale data in the cache
extended-salmon
extended-salmonOP2y ago
For the first one, yes the data will be there. But not the second one
fair-rose
fair-rose2y ago
Could you record a video?
extended-salmon
extended-salmonOP2y ago
extended-salmon
extended-salmonOP2y ago
For this I had pendingMs at 1500 And added artificial 2000ms delay in the second call so it wouldn't be too quick
fair-rose
fair-rose2y ago
I’m shipping a few updates tonight that might fix this issue. Obviously, if they don’t, I’m happy to keep digging deeper
extended-salmon
extended-salmonOP2y ago
Awesome, thank you 🙂 I tried with the latest version and the problem persists Here is a minimal repro: https://stackblitz.com/edit/tanstack-router-wcrnyc?file=src%2Froutes%2Findex.tsx
fair-rose
fair-rose2y ago
Add gcTime: 0 to your data route What's happening: - The first load has nothing cached in the router, so it waits - The second load has a cache entry in the router and thus begins to render right away while running the loader in the background and updates it later gcTime: 0 tells the route to not cache anything (or more specifically, garbage collect the route's data immediately after storing it) If you *always want your routes to wait in loader, no matter what, you can turn off caching globally with the router's defaultGcTime: 0 option
extended-salmon
extended-salmonOP2y ago
Awesome, that fixed it. Thank you 🙂

Did you find this page helpful?