#preload data

4 messages · Page 1 of 1 (latest)

analog pagoda
#

how can I preload data so that useQuery doesnt return undefined?

raven treeBOT
#

Hi @analog pagoda. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

To preload data so that useQuery doesn't return undefined on first render, you have a few options depending on your stack:

1. Next.js (App Router or Pages Router)

With Next.js, you can use the preloadQuery function from convex/nextjs in a Server Component to fetch data before rendering your Client Component. Then, in your Client Component, use usePreloadedQuery to access the preloaded data. This approach ensures that your component has data immediately and avoids the initial undefined state.

Example:

Server Component:

import { preloadQuery } from "convex/nextjs";
import { api } from "@/convex/_generated/api";
import ClientComponent from "./ClientComponent";

export async function ServerComponent() {
  const preloaded = await preloadQuery(api.foo.baz);
  return <ClientComponent preloaded={preloaded} />;
}

Client Component:

import { Preloaded, usePreloadedQuery } from "convex/react";
import { api } from "@/convex/_generated/api";

export function ClientComponent(props: { preloaded: Preloaded<typeof api.foo.baz> }) {
  const data = usePreloadedQuery(props.preloaded);
  // render `data`...
}

This pattern ensures that the data is available immediately in the client component, avoiding the undefined loading state from useQuery alone.
See docs for details <source><https://docs.convex.dev/client/nextjs/app-router/server-rendering</source>.>

2. TanStack Query

If you are using TanStack Query, you can use ensureQueryData in a loader to preload data before rendering, and then use useSuspenseQuery or useQuery in your component. This approach is supported in frameworks like TanStack Start, which integrates well with Convex.

#

Example:

export const Route = createFileRoute('/posts')({
  loader: async (opts) => {
    await opts.context.queryClient.ensureQueryData(
      convexQuery(api.messages.list, {}),
    );
  },
  component: () => {
    const { data } = useSuspenseQuery(convexQuery(api.messages.list, {}));
    return (
      <div>
        {data.map((message) => (
          <Message key={message.id} post={message} />
        ))}
      </div>
    );
  },
});

This ensures the data is loaded before the component renders, so you avoid the initial loading state.
See TanStack docs for more <source><https://docs.convex.dev/client/tanstack/tanstack-start/#server-side-rendering</source>.>


Note:
If you are using plain useQuery from Convex React (not with Next.js or TanStack), there is no built-in way to preload data to avoid the initial undefined state. The recommended pattern is to check for undefined and show a loading indicator. For more advanced use cases (like avoiding loading flashes when query arguments change), you can implement a custom hook like useStableQuery to keep showing stale data until new data is loaded, but this does not preload data before the first render <source><https://stack.convex.dev/help-my-app-is-overreacting#impacting-how-the-querys-reacting</source>.>


Summary:

  • Use preloadQuery + usePreloadedQuery in Next.js for preloading.
  • Use TanStack Query's ensureQueryData for preloading in TanStack Start.
  • Plain Convex React does not support preloading for useQuery—you must handle the loading state.

Let me know if you need a code example for your specific stack!

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: