Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/get-convex/convex-react-query/llms.txt

Use this file to discover all available pages before exploring further.

convexQuery is a query options factory that wires TanStack Query’s useQuery to a Convex query function subscription. Results are pushed from the server whenever the underlying data changes — no polling, no staleTime expiry, no manual invalidation.

Basic usage

Pass a function reference from your generated api object and its arguments to convexQuery, then hand the result directly to useQuery.
import { useQuery } from "@tanstack/react-query";
import { convexQuery } from "@convex-dev/react-query";
import { api } from "../convex/_generated/api";

const { data, isPending, error } = useQuery(
  convexQuery(api.messages.list, {})
);
staleTime is set to Infinity automatically because Convex pushes fresh results proactively — the data is never stale in the traditional polling sense.

Queries with arguments

Pass an arguments object as the second parameter. The function reference and the arguments together form the query key.
const { data } = useQuery(
  convexQuery(api.messages.search, { query: searchTerm, limit: 5 })
);

Conditional / skippable queries

Pass the string "skip" in place of an arguments object to disable the query conditionally.
// Pass "skip" to disable the query conditionally
const { data, isPending } = useQuery(
  convexQuery(api.messages.count, shown ? {} : "skip")
);
When "skip" is passed, enabled: false is set automatically and the query won’t run. No subscription is created and no request is made.

Suspense support

convexQuery is compatible with useSuspenseQuery. Wrap the component in a <Suspense> boundary to handle the loading state declaratively.
import { useSuspenseQuery } from "@tanstack/react-query";
import { Suspense } from "react";

function MessageCount() {
  const { data } = useSuspenseQuery(convexQuery(api.messages.count, {}));
  return <div>{data} messages</div>;
}

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <MessageCount />
    </Suspense>
  );
}
Actions (convexAction) cannot be used with useSuspenseQuery because they are not reactive and do not push updates.

Controlling subscription lifetime

The Convex WebSocket subscription stays active until TanStack Query’s gcTime elapses after all observers have unmounted. Tune gcTime to balance responsiveness against bandwidth usage.
const { data } = useQuery({
  ...convexQuery(api.messages.list, {}),
  gcTime: 10000, // unsubscribe 10s after all useQuery hooks unmount
});
The default gcTime in TanStack Query is 5 minutes. For most apps a value of a few seconds is a better tradeoff — it lets fast navigation reuse a cached result without holding the subscription open indefinitely.

Extra query options

Spread convexQuery into an options object to add initialData, placeholderData, or any other TanStack Query option.
const { data } = useQuery({
  ...convexQuery(api.messages.list, {}),
  initialData: [],
  placeholderData: [],
});

Using convexQueryClient.queryOptions()

ConvexQueryClient exposes a queryOptions() method that works the same way as convexQuery but embeds its own queryFn directly, so you don’t need to configure a global default queryFn.
const { data } = useQuery(
  convexQueryClient.queryOptions(api.messages.list, {})
);
Unlike convexQuery, convexQueryClient.queryOptions() does NOT require the global queryFn to be set on the QueryClient. Use it when you prefer explicit per-query configuration over a global default.