Nerdkidchiki
Nerdkidchiki7mo ago

Tanstack Router + Convex

i would love to fetch most of my data at the route level rather than in components
10 Replies
erquhart
erquhart7mo ago
Tanstack router seems to more favor ensuring data is ready for the component than actually loading it and passing it to the component from what I've seen
erquhart
erquhart7mo ago
Consider this example from their docs using TanStack Query, and also that Convex is an "external" data source, so you'll want to handle it differently than local app state: https://tanstack.com/router/latest/docs/framework/react/guide/external-data-loading#a-more-realistic-example-using-tanstack-query
External Data Loading | TanStack Router React Docs
[!IMPORTANT] This guide is geared towards external state management libraries and their integration with TanStack Router for data fetching, ssr, hydration/dehydration and streaming. If you haven't read the standard Data Loading guide, please do so first.
erquhart
erquhart7mo ago
Specifically looking at this:
// Use the `loader` option to ensure that the data is loaded
loader: () => queryClient.ensureQueryData(postsQueryOptions),
// Use the `loader` option to ensure that the data is loaded
loader: () => queryClient.ensureQueryData(postsQueryOptions),
I've used this in my loader to make sure Convex has data ready, but then I still use useQuery in the component to fetch the data. (also check out the Convex integration w/ TanStack Query to help with this: https://docs.convex.dev/client/tanstack-query)
Nerdkidchiki
NerdkidchikiOP7mo ago
i am not using @tanstack-query...i wanna know how i will fetch data in the loader directly with convex...i dont wanna integrate @tanstack-query with convex
erquhart
erquhart7mo ago
Okay, you don't have to, but those docs I linked are TanStack router's recommended approach for loading data from "external state management libraries", and Convex fits that category. I don't generally use Tanstack Query at the moment, but I've found it makes it easier when working with TanStack router. Even if just for working with ensureQueryData(), but maybe that's just me being lazy. Either way, treat Convex as an external state lib and you'll be on the right track.
Nerdkidchiki
NerdkidchikiOP7mo ago
thanks so much for the reference to the tanstack-router docs...but thats exactly where i am coming from before asking the question.....lemme ask the question properly seeing i cannot call the convex useQuery hook in the loader function...what then do i call to fetch the data?....basically...does convex have a no hook api to fetch data in functions outside React?...please dont tell me to use the http actions 😢
erquhart
erquhart7mo ago
Absolutely! There's a js client that you can use directly, I'm just saying that you're working against the tools you've chosen (Tanstack, Convex, and React) if you use it that way. I'll grab the link
erquhart
erquhart7mo ago
JavaScript | Convex Developer Hub
Convex applications can be accessed from Node.js or any JavaScript runtime that
erquhart
erquhart7mo ago
As an example of what I'm recommending, though, here's how I ensure I have a user before loading an authenticated route with Convex + TanStack router:
export const Route = createFileRoute('/dashboard/_layout')({
component: DashboardLayout,
beforeLoad: async ({ context, location }) => {
await context.queryClient.ensureQueryData(
convexQuery(api.app.getCurrentUser, {}),
)
if (!context.user) {
throw redirect({
to: AuthLoginRoute.fullPath,
search: {
redirect: location.href,
},
})
}
},
})

function DashboardLayout() {
const { data: user } = useQuery(convexQuery(api.app.getCurrentUser, {}))

// This is just here to make TypeScript happy
if (!user) {
return null
}

return (
<div className="flex min-h-[100vh] w-full flex-col bg-secondary dark:bg-black">
<Navigation user={user} />
<Header />
<Outlet />
</div>
)
}
export const Route = createFileRoute('/dashboard/_layout')({
component: DashboardLayout,
beforeLoad: async ({ context, location }) => {
await context.queryClient.ensureQueryData(
convexQuery(api.app.getCurrentUser, {}),
)
if (!context.user) {
throw redirect({
to: AuthLoginRoute.fullPath,
search: {
redirect: location.href,
},
})
}
},
})

function DashboardLayout() {
const { data: user } = useQuery(convexQuery(api.app.getCurrentUser, {}))

// This is just here to make TypeScript happy
if (!user) {
return null
}

return (
<div className="flex min-h-[100vh] w-full flex-col bg-secondary dark:bg-black">
<Navigation user={user} />
<Header />
<Outlet />
</div>
)
}
I suspect Route.useLoaderData() makes more sense with a fetch operation than with a websocket based realtime client like Convex, but I haven't actually tested this to see what happens.
Nerdkidchiki
NerdkidchikiOP7mo ago
wow.....seems nice...i was just really trying to avoid using React query as i feel it will add extra complexity seeing i am still just a learner.....i guess this pattern is better tho....i will dive into the docs...thanks so much 👍

Did you find this page helpful?