Preloading data in Server Components Next.js
I don't seem to find anything in docs in regards to preloading data? I might be completely misunderstanding something, since coming from React Query.
But is there a way to preload some data on the server, and then passing that to the local store, so there is data already there when the user first loads a page?
14 Replies
We've prototyped integrated approaches like this before but we currently recommend passing the data through and then defaulting to it manually at the
useQuery()
call site with const data = useQuery(api.foo.bar) || preloadedData
And the way to fetch data on the web server would be to use a Node.js client to fetch it from convex
https://docs.convex.dev/client/javascript/node
and especially
https://docs.convex.dev/client/react/nextjs/#server-side-rendering
are good resources here
Node.js | Convex Developer Hub
Convex supports point-in-time queries (see
Next.js | Convex Developer Hub
How Convex works in a Next.js app
(Actually it's the ConvexHTTPClient, which is not Node.js specific, see
https://docs.convex.dev/client/javascript#http-client
)
JavaScript | Convex Developer Hub
Convex applications can be accessed from Node.js or any JavaScript runtime that
Awesome thanks to both of you. Just curious, in terms of a nice UX when the data is loading? is there a recommended way of doing this from you guys
It's a minor thing, but i see a slight flash of content when loading moving between pages, when the cache is being loaded. I don't find it to be fixable with a loading indicator as that would be flashing in out quickly too.
Yeah thanks. I did play with the ConvexHTTPClient in my server component that worked perfectly fine. So i guess passing that down with the approach tom mentioned would work, im gonna test that out.
I'd say the simplest approach is to keep things clientside (no preloading), but use a nice fade-in animation for the loading. You can do thinks like not show a skeleton if the loading takes more than x ms.
The challenge with preloading is that without an integrated approach you have to handle each query twice (on client with useQuery and on server with HTTPClient), which can be cumbersome - but if you can load some small simple data to get the page loading, it can work well. Really depends on your app.
That makes sense, was thinking about some sort of skeleton UI even though i haven't tried this approach before in my previous apps. Thanks for clearing this up for me Michael.
I agree, i also see the whole preloading thing bringing issues with it. So yeah it might fix the whole having data visible to the user straight away, but the approach u mention def seems like a good balance of easy to do and still nice experience for the user
A bit advanced, but You can preload the query or keep it around between pages by using the
convex.wathQuery
function to make a Watch that you can use to hold a long-standing subscription open with onUpdate
which returns a function to unsubscribe when you're no longer interested. You could theoretically pre-warm queries and keep them active for certain pages of your client-routed app.this ⬆️ is pretty slick, we've seen folks do this on button/link hover: if you know what queries a view will need and the Convex Provider (or the ConvexReactClient it provides) persists between two views, you can
Awesome stuff, really cool approach with pre-warming the queries on button hover. I can see this working great 🤩
sorry to hijack this thread. i think it's relevant to what i have in mind
say i wanted to do the above in my client side page, because
userId
takes a while to load, the access
value im getting goes from undefined -> false -> true. i think it'd be better for me to do server side for this part. what do y'all think?What are your goals or your concerns with this approach?
Yeah combining multiple queries into one is often a good approach.
Check out "skip" in the useQuery() docs to avoid passing an empty string fake userId if you want to do avoid that
thanks so much tom. it flashes a sec for the "falsy" component then shows the true component
You probably want all three values, undefined and false and true: undefined means loading, false means this user is not allowed (show the NOT ALLOWED UI), true means allowed
got it, yeah skip should help with making that false undefined i stead
damn it worked
hello @convex_CEO, pls give tom a raise 🙂
ugh i should have studied the doc 😛