Corbi-Wan Kenobi
Corbi-Wan Kenobi•2w ago

When to query data in a framework's loader vs a route component? Or imported component?

Coming from a Remix/RR7 background where basically all data fetching was done in the loader. Now I'm making headway in TanStack Start/Router and Convex and its slowly starting to click. Convex docs for TanStack always show doing a query in the route component, usually highlighting the reactivity for changes in the database which is great. My questions are, under what circumstances would one do the query in a loader/beforeLoad and when would one do it in the route component? When reactivity is needed is it only achieved in the route component? Can reactivity happen from an imported component that has a useQuery in its export? If one doesn't need reactivity is it better to query in the loader? Some of this has to do with the code splitting that TanStack does, keeping code securely processed on the server vs potentially exposed on the client. How that all works is one of the many ways my ignorance starts to show. Like anyone else, I want to keep safe the data that needs keeping safe, and also have the app do the work where it should be doing it (loader/component/route) and not mistakenly trying to make it do it one way when it only works the other.
13 Replies
Convex Bot
Convex Bot•2w ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
ballingt
ballingt•2w ago
Some of this has to do with the code splitting that TanStack does, keeping code securely processed on the server vs potentially exposed on the client
At least for the parts of your app that use Convex, you're already safe here! Convex functions always only run on the convex deployment (the convex server).
under what circumstances would one do the query in a loader/beforeLoad and when would one do it in the route component?
Anything in a loader runs during SSR and during a preload (by default, hover over the link to the page). So start loading in the loader if you want to get a head start on loading a query, or block with await ensureQuery in the loader if you never want your route to load without the query already being loaded.
When reactivity is needed is it only achieved in the route component?
Yep, you don't get reactivity unless you use useQuery().
Can reactivity happen from an imported component that has a useQuery in its export?
I don't understand this, could you give an example? Any component that uses useQuery() with a Convex query will be reactive, it doesn't matter where you import it from.
If one doesn't need reactivity is it better to query in the loader?
Loading is generally "better" in the loader, since you get to take advantage of preloading—whether you need reactivity or not. If you don't want reactivity, avoid using useQuery(), since that will keep the query live.
Corbi-Wan Kenobi
Corbi-Wan KenobiOP•2w ago
What does it look like to subscribe to a dynamic route in the loader? Can't use useQuery because its a invalid hook call. I have it working non-reactive. export const Route = createFileRoute("/events/$eventId")({ component: Event, loader: async ({ context, params }) => { return await context.queryClient.fetchQuery( convexQuery(api.events.getEvent, { eventId: params.eventId as Id<"events">, }), ); }, }); I'm scrubbing through your Building with TanStack Start and Convex Demo youtube looking for inspiration. 🙂
ballingt
ballingt•2w ago
Also see https://convex-tanstack-start.vercel.app/ for some info
subscribe to a dynamic route in the loader
"Subscribing" usually means you want live updates, but loaders only run once, when the page loads. All you need to add to this is a useQuery() in the component
Corbi-Wan Kenobi
Corbi-Wan KenobiOP•2w ago
Oops, word context. I was scrubbing through the video meaning quickly scanning.
ballingt
ballingt•2w ago
I mean re
What does it look like to subscribe to a dynamic route in the loader?
That's not something you can do because loaders only run once. You need to use useQuery() to subscribe to the changes
Corbi-Wan Kenobi
Corbi-Wan KenobiOP•2w ago
Oh man. I can't read today! Scribbing/Subscribe = mild dyslexia! OK, so, if I can't call useQuery in the loader, and the Route const is where the params are called, how do I use useQuery to subscribe to a dynamic route with params? Do I do something like make a const evenId = params.eventId in the loader and pass that via useLoaderData to the component to then have it to use in UseQuery? or can I call params in the component also and not just up tine Route const?
Corbi-Wan Kenobi
Corbi-Wan KenobiOP•2w ago
Yeah, thats the fly in the ointment.
ballingt
ballingt•2w ago
this is closer https://github.com/get-convex/convex-tanstack-start/blob/8eb95a0f1a20f57ed9c26263b923c0e0870096ad/app/routes/loaders/ensure.tsx So forgetting loaders for a sec, you can access params in the component. Do a useQuery with that. But then the fun thing about loaders is they let you preload, so that the useQuery is never undefined. You can await context.queryClient.ensureQueryData(... to block the component from rendering until this data is available. But either way, the way you load data in the component is the same, useQuery()
Corbi-Wan Kenobi
Corbi-Wan KenobiOP•2w ago
OK, so how do I call/refer to params in the component? I'm going to try to figure it out first based on the example, but the example doesn't specifically use params
ballingt
ballingt•2w ago
I think it's Route.useSearch() for query params, and Route.useParams() for path parameters https://tanstack.com/router/v1/docs/framework/react/guide/path-params#path-params-in-components
Corbi-Wan Kenobi
Corbi-Wan KenobiOP•2w ago
Perfect. Thanks for the direction. OK, that's way too easy.

Did you find this page helpful?