> ## 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.

# Convex React Query

> Real-time reactive Convex queries with TanStack Query — zero polling, zero stale data.

`@convex-dev/react-query` bridges [Convex](https://convex.dev) real-time subscriptions with [TanStack Query](https://tanstack.com/query), giving you live-updating data in your React app without polling or manual cache invalidation.

When a Convex query result changes on the server, the update is pushed to your client instantly. Your TanStack Query cache stays fresh automatically — no `queryClient.invalidateQueries()` needed.

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Install the package and wire up your first reactive query in minutes.
  </Card>

  <Card title="How it works" icon="gear" href="/concepts/how-it-works">
    Learn how Convex subscriptions integrate with the TanStack Query cache.
  </Card>

  <Card title="API Reference" icon="code" href="/api/convex-query-client">
    Full reference for `ConvexQueryClient`, `convexQuery`, and `convexAction`.
  </Card>

  <Card title="Guides" icon="book-open" href="/guides/queries">
    Deep dives into queries, mutations, authentication, and SSR.
  </Card>
</CardGroup>

## Why use this library?

Convex pushes new query results to your client over a WebSocket whenever the underlying data changes. TanStack Query is the most popular data-fetching library for React. This adapter connects them so you can use the full TanStack Query API — `useQuery`, `useSuspenseQuery`, `useMutation`, devtools, and more — while getting Convex's real-time guarantees for free.

<CardGroup cols={2}>
  <Card title="No stale data" icon="bolt">
    Results are pushed from the server; `staleTime: Infinity` is set automatically so TanStack Query never marks Convex data as stale.
  </Card>

  <Card title="No manual invalidation" icon="ban">
    Forget `invalidateQueries()`. The `ConvexQueryClient` updates the cache whenever the server pushes a new result.
  </Card>

  <Card title="Type-safe queries" icon="shield-check">
    Full TypeScript inference for function arguments and return types using Convex's generated `api` object.
  </Card>

  <Card title="SSR ready" icon="server">
    Fetch consistent query snapshots on the server with `ConvexHttpClient` and hydrate on the client.
  </Card>
</CardGroup>

## Quick look

```tsx quickstart.tsx theme={null}
import { useQuery } from "@tanstack/react-query";
import { convexQuery } from "@convex-dev/react-query";
import { api } from "../convex/_generated/api";

function MessageList() {
  const { data, isPending } = useQuery(convexQuery(api.messages.list, {}));

  if (isPending) return <div>Loading...</div>;
  return (
    <ul>
      {data.map((msg) => (
        <li key={msg._id}>{msg.body}</li>
      ))}
    </ul>
  );
}
```

<Steps>
  <Step title="Install the package">
    Add `@convex-dev/react-query` along with its peer dependencies.

    ```bash theme={null}
    npm install @convex-dev/react-query @tanstack/react-query convex
    ```
  </Step>

  <Step title="Create ConvexQueryClient">
    Instantiate a `ConvexQueryClient` and connect it to your TanStack `QueryClient`.

    ```ts theme={null}
    const convexClient = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);
    const convexQueryClient = new ConvexQueryClient(convexClient);
    const queryClient = new QueryClient({
      defaultOptions: {
        queries: {
          queryKeyHashFn: convexQueryClient.hashFn(),
          queryFn: convexQueryClient.queryFn(),
        },
      },
    });
    convexQueryClient.connect(queryClient);
    ```
  </Step>

  <Step title="Wrap your app">
    Provide both clients to your React tree.

    ```tsx theme={null}
    <ConvexProvider client={convexClient}>
      <QueryClientProvider client={queryClient}>
        <App />
      </QueryClientProvider>
    </ConvexProvider>
    ```
  </Step>

  <Step title="Query with convexQuery">
    Use `useQuery` with the `convexQuery` options factory for live-updating data.

    ```tsx theme={null}
    const { data } = useQuery(convexQuery(api.messages.list, {}));
    ```
  </Step>
</Steps>
