@confect/react provides drop-in replacements for Convex’s React hooks. Each hook automatically encodes your args and decodes return values through the Effect Schemas defined in your function specs. You work with the Schema Type (decoded) values on both sides—the hooks handle the round-trip to Convex’s Encoded representation transparently.
Functions are referenced via refs (from confect/_generated/refs) instead of Convex’s api object. Each ref carries the args, returns, and (optionally) error schemas from the corresponding function spec, which is what enables the automatic encoding and decoding.
Setup
The React provider setup is the same as vanilla Convex.src/main.tsx
useQuery
Encodes args using the spec’s args schema, passes them to Convex, and decodes the result using the spec’s returns schema. Returns a QueryResult<A, E>—a tagged union with Loading, Success, and Failure variants.
Given this spec:
confect/notes.spec.ts
{} (the Type of Schema.Struct({})) as args and returns a QueryResult<readonly notes.Doc["Type"][]>. Match it with QueryResult.match:
QueryResult also exposes the lower-level predicates QueryResult.isLoading, QueryResult.isSuccess, and QueryResult.isFailure for cases where pattern matching is awkward.
Typed errors
When the ref’s spec declares anerror schema, useQuery returns QueryResult<A, E> and QueryResult.match requires an onFailure handler that receives the decoded typed error. See Error Handling for how to declare error schemas.
error schema are not surfaced as Failure. They propagate the same way they do with convex/react’s useQuery (typically reaching the nearest error boundary).
Skipping queries
Pass"skip" instead of args to disable the query subscription. The hook returns a Loading variant whose skipped flag is true, which lets you distinguish a query that is genuinely in flight from one sitting idle because no args have been provided.
usePaginatedQuery
Loads data reactively from a paginated query, mirroring the ergonomics of usePaginatedQuery from convex/react. The ref must come from a spec defined with FunctionSpec.publicPaginatedQuery — passing any other ref fails at runtime with an error pointing at the constructor.
Args are encoded using the spec’s user-args schema (paginationOpts is managed by the hook, not the caller), and each loaded page is decoded using the spec’s item schema. Pass "skip" instead of args to disable the query, like useQuery.
Returns a PaginatedQueryResult<Item, E>. The loaded variants — LoadingFirstPage, LoadingMore, CanLoadMore, and Exhausted — all carry results and isLoading, and CanLoadMore additionally carries loadMore, so the common UI needs only field access and a couple of predicates:
loadMore lives only on CanLoadMore, the one state it can make progress from — the underlying Convex hook exposes it on every status, but calling it while a page is in flight, once the list is exhausted, or after a failure is an intentional no-op there. Narrowing with isCanLoadMore (or match’s onCanLoadMore) makes that statically apparent instead of silently dropping the call.
PaginatedQueryResult also provides match for exhaustive pattern matching, and the predicates isLoadingFirstPage, isLoadingMore, isExhausted, isLoading, and isFailure.
Typed errors
When the spec declares anerror schema, the result type gains a Failure variant carrying the decoded typed error — errors are values, consistent with useQuery. Narrow with PaginatedQueryResult.isFailure (or handle onFailure in match) to reach it:
results, Failure included: when a later page fails, the pages already loaded are not discarded.
Without an error schema, the Failure variant is excluded from the type entirely, so no narrowing is needed. Failures not declared in the error schema are thrown during render and propagate to the nearest error boundary.
usePaginatedQuery requires convex 1.36.0 or newer.useMutation
Returns a function that encodes args using the spec’s args schema, calls the Convex mutation, and decodes the result using the spec’s returns schema. The returned promise’s shape depends on whether the spec declares an error schema.
Without an error schema
The function returns Promise<A>, matching convex/react’s useMutation. Undeclared failures still reject the promise.
confect/notes.spec.ts
With an error schema
When the spec declares an error schema, the function returns Promise<Either<A, E>>. Unwrap with Either.match (or another Either combinator) to handle both branches. Undeclared failures still reject the promise.
confect/notes.spec.ts
useAction
Same shape as useMutation: returns Promise<A> when the ref has no error schema, and Promise<Either<A, E>> when it does.
confect/random.spec.ts