Convex provides React hooks to seamlessly integrate your Convex backend with React applications. These hooks manage subscriptions, loading states, and reactivity automatically.
Load reactive query data within a React component.
import { useQuery } from "convex/react";import { api } from "../convex/_generated/api";function TaskList() { const tasks = useQuery(api.tasks.list, { completed: false }); if (tasks === undefined) return <div>Loading...</div>; return tasks.map((task) => <div key={task._id}>{task.text}</div>);}
This hook subscribes to a Convex query and causes a rerender whenever the query result changes. The subscription is managed automatically - it starts when the component mounts and stops when it unmounts.
This hook is similar to useQuery but allows loading multiple queries, which is useful for a dynamic number of queries without violating React hooks rules.
An object whose keys are identifiers and values are objects containing query (function reference) and args (arguments object).
Returns: An object with the same keys as the input. Values are the query result, undefined if still loading, or an Error if the query threw an exception.
This hook is designed for “infinite scroll” UIs. It concatenates all pages of results into a single list and manages continuation cursors automatically.
Actions can call third-party APIs and perform side effects. The returned function is stable across renders.
In most cases, calling an action directly from a client is an anti-pattern. Prefer having the client call a mutation that captures the user’s intent (by writing to the database) and then schedules the action via ctx.scheduler.runAfter. This ensures the intent is durably recorded even if the client disconnects.
Get the ConvexReactClient within a React component.
import { useConvex } from "convex/react";function MyComponent() { const convex = useConvex(); // Use the client directly const handleClick = async () => { const result = await convex.query(api.myQuery, {}); }; return <button onClick={handleClick}>Fetch</button>;}
This relies on ConvexProvider being above in the React component tree.Returns: The active ConvexReactClient instance.Throws: An error if not used under ConvexProvider.
This hook returns the current connection state and automatically rerenders when any part of the connection state changes.Returns: A ConnectionState object.Throws: An error if not used under ConvexProvider.
This hook provides the current authentication state when using ConvexProviderWithAuth or a similar auth integration provider. It relies on an auth provider being above in the React component tree.Returns: A ConvexAuthState object containing:
Whether the user is currently authenticated with Convex. true only when both the auth provider reports authentication and Convex has successfully validated the token.
Throws: An error if not used under ConvexProviderWithAuth or a similar auth integration provider like ConvexProviderWithClerk.
A replacement for ConvexProvider that integrates any auth provider with Convex.
import { ConvexProviderWithAuth, ConvexReactClient } from "convex/react";import { useAuth } from "@myauth/react";const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL);function App() { return ( <ConvexProviderWithAuth client={convex} useAuth={useAuth}> <YourApp /> </ConvexProviderWithAuth> );}
This component wraps ConvexProvider and additionally provides ConvexAuthState to descendant components. Use this to integrate any auth provider with Convex by passing a custom useAuth hook.If the useAuth hook updates (causing a rerender), the auth state will transition to loading and fetchAccessToken() will be called again. This enables dynamic auth context changes like switching organizations.See Custom Auth Integration for more information.