Recommended pattern for initializing useQuery with server loaded value
Hey folks,
Is there a recommended NextJS-compatible pattern for initializing a useQuery hook with a result from the server so that initial page load is very snappy but subsequent changes are fully reactive? (I realize this involves double fetching)
e.g.
Here's a hypothetical implementation of such a function:
11 Replies
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!
Hi! did you see this? https://docs.convex.dev/client/react/nextjs/server-rendering
Next.js Server Rendering | Convex Developer Hub
Next.js automatically renders both Client and Server Components on the server
This is exactly what I was looking for @jamwt. Appreciate the reply and sorry I missed this. Loving Convex, keep up the great work!
Minor follow up question: any pointers (maybe a community implementation?) on how to implement a wrapper around
usePreloadedQuery
to support using React Suspense
for implementing loading states? I'm struggling to adapt the useQuery
example wrapper for Suspense
for usePreloadedQuery
. See: https://discord.com/channels/1019350475847499849/1295933266200891452hmm. @ballingt might have some ideas. he's defintely been pursuing this route on the tanstack start side
We have some code for this, but what's the behavior you want here? You want to stream the promise for the preload from a server component, then resume live? I would probably either wait for the data on the server (which could cause a suspend, but that's not a convex hook thing) or just client side render if you want a loading state.
This is possible but we want to be clear about the behavior you want
@ballingt: Yea it's a little bit niche: my desired behavior is that the initial page load be preloaded with data that is fetched server side and waited on, and then resumes live after client side render (no loading UI in this case).
However, for my use case, after client side render, certain actions can be taken that will result in fetching new data. It's in response to these client side actions that I want to display loading UI. I'm able to do this with
result === undefined
checks, but I prefer the Suspense
/ Boundary
patterns, so I was hoping to have the option to somehow use usePreloadedQuery
to achieve this.
To summarize, I want the following behavior:
1. Preload data server side with await preloadQuery
(no loading UI necessary)
2. Resume live client side with usePreloadedQuery
3. Support subsequent client side actions that refetch all data (display loading UI using Suspense
ideally)
To make it more concrete, I made a Loom video of the UI I'm working on: https://www.loom.com/share/05feb91800354a0396be12a0793a4d1a.
In the video, the chat messages are initially preloaded with no loading state. But I want to display loading state when you select a new chat from the dropdown.
Please let me know if I can provide any additional context. Appreciate the help here!That makes sense! We've prototyped this, blocking on the server but suspense on the client.
The first thing we might do is expose a stable promise for the data having loaded so you can suspend yourself
I'm not sure what to call this hook, it's a confusing behavior to describe but it makes sense that it's often what you'd want
That sounds great, @ballingt! I know you're all super busy so I don't expect much here but any sense of when y'all might be able to get around to exposing such a promise?
It's going to be a bit, likely this would be in convex-helpers or a community recipe first
mostly because we'd like to try using it for a while before pushing people toward it
I'm doing some work on TanStack Start examples and this may come up, but there we're using TanStack Query to do these pieces
Have you seen existing suspense wrapper hooks for Convex? There's nothing in "convex/react" but there are community recipes
if you want to play with this today using
useSuspenseQuery()
from TanStack Query is the simplest way today https://docs.convex.dev/client/tanstack-query
This is a bit of work that it sounds like you've already looked at, it needs to replace the convex/react useQuery (rewrite some of the internals), it can't just wrap itHere's an implementation: https://github.com/get-convex/ents-saas-starter/blob/gold/lib/convex-gold-nextjs/index.tsx
GitHub
ents-saas-starter/lib/convex-gold-nextjs/index.tsx at gold · get-co...
Convex, Clerk, Next.js, Convex Ents. Contribute to get-convex/ents-saas-starter development by creating an account on GitHub.
https://github.com/get-convex/ents-saas-starter/blob/e386710de96b0cd39cf5eb3c3ae95105ef2f7ae4/lib/convex-gold-nextjs/index.tsx#L31-L51
something like
@stcobbe it's helpful to hear this specifically requested! This is a pattern that makes sense. I'll probably implement it in TanStack Start first where we have more reliable data injection SSR primitives (although I think Next.js has added made these more stable now? I need to catch up)