Skip to main content
@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 and returns 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
import { ConvexProvider, ConvexReactClient } from "convex/react";
import React from "react";
import ReactDOM from "react-dom/client";

import App from "./App";

const convexClient = new ConvexReactClient(
  import.meta.env.VITE_CONVEX_URL,
);

ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement,
).render(
  <React.StrictMode>
    <ConvexProvider client={convexClient}>
      <App />
    </ConvexProvider>
  </React.StrictMode>,
);

useQuery

Encodes args using the spec’s args schema, passes them to Convex, and decodes the result using the spec’s returns schema. Returns T | undefined (undefined while loading), matching Convex’s useQuery. Given this spec:
confect/notes.spec.ts
import { FunctionSpec, GroupSpec } from "@confect/core";
import { Schema } from "effect";

import { Notes } from "./tables/Notes";

export const notes = GroupSpec.make("notes").addFunction(
  FunctionSpec.publicQuery({
    name: "list",
    args: Schema.Struct({}),
    returns: Schema.Array(Notes.Doc),
  }),
);
The hook accepts {} (the Type of Schema.Struct({})) as args and returns readonly Notes.Doc["Type"][] (the Type of Schema.Array(Notes.Doc)):
import { useQuery } from "@confect/react";
import refs from "../confect/_generated/refs";

const NoteList = () => {
  const notes = useQuery(refs.public.notes.list, {});

  if (notes === undefined) {
    return <p>Loading…</p>;
  }

  return (
    <ul>
      {notes.map((note) => (
        <li key={note._id}>{note.text}</li>
      ))}
    </ul>
  );
};

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. Returns (args) => Promise<T>, matching Convex’s useMutation. Given this spec:
confect/notes.spec.ts
FunctionSpec.publicMutation({
  name: "insert",
  args: Schema.Struct({ text: Schema.String }),
  returns: GenericId.GenericId("notes"),
});
The returned function accepts { text: string } (the Type of the args schema) and returns a Promise<GenericId<"notes">> (the Type of the returns schema):
import { useMutation } from "@confect/react";
import refs from "../confect/_generated/refs";

const InsertNote = () => {
  const insertNote = useMutation(refs.public.notes.insert);

  return (
    <button onClick={() => void insertNote({ text: "Hello" })}>
      Insert note
    </button>
  );
};

useAction

Same pattern as useMutation: encodes args via the spec’s args schema, calls the Convex action, and decodes the result via the spec’s returns schema. Returns (args) => Promise<T>. Given this spec:
confect/random.spec.ts
FunctionSpec.publicAction({
  name: "getNumber",
  args: Schema.Struct({}),
  returns: Schema.Number,
});
The returned function accepts {} and returns a Promise<number>:
import { useAction } from "@confect/react";
import refs from "../confect/_generated/refs";

const RandomNumber = () => {
  const getRandom = useAction(refs.public.random.getNumber);

  const handleClick = () => {
    void getRandom({}).then(console.log);
  };

  return <button onClick={handleClick}>Get random</button>;
};

Differences from vanilla Convex hooks

Vanilla ConvexConfect
Functions referenced via api.module.fnFunctions referenced via refs
Args passed directly to Convex as-isArgs are schema-encoded from Type to Encoded before sending to Convex
Return values received directly from Convex as-isReturn values are schema-decoded from Encoded to Type before returning