To get started with React quickly, scaffold a new project with npm create your-app-name. Check out main.tsx (opens in a new tab) and App.tsx (opens in a new tab) from the scaffold.

The react integration is provided by the (opens in a new tab) package and centers around:

  1. A useQuery hook that allows you to subscribe to a query and get the data in your component.
  2. A DBProvider (opens in a new tab) to provide one or more databases to your component tree and kick off sync.



> npm install


import { useQuery } from "";
import tblrx from "";



type QueryData<T> = {
  readonly loading: boolean;
  readonly error?: Error;
  readonly data: T;
type CtxAsync = {
  readonly db: DBAsync;
  readonly rx: TblRx;
function useQuery<R, M = R[]>(
  ctx: CtxAsync,
  query: SQL<R>,
  bindings?: any[],
  postProcess?: (rows: R[]) => M
): QueryData;


  • ctx - The context object that contains the database and rx-tbl instance.
  • query - The query to run.
  • bindings - The bindings to use for the query (optional)
  • postProcess - A function to post process the data (optional)


function MyComponent({ctx}) {
  const { data, loading, error } = useQuery(ctx, "SELECT * FROM users WHERE country = ?", ["NZ"]);
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  return (
      { => (
        <li key={}>{}</li>


Returns the first element of an array or undefined if the array is empty. Useful for queries that return a single row.

function first<T>(data: T[]): T | undefined;


const countRow = useQuery(ctx, "SELECT count(*) as c FROM users", null, first).data;
const count = countRow?.c;


Returns the first column of the first element of an array or undefined if the array is empty. Useful for queries that return a single row and a single column.

function firstPick<T>(data: any[]): T | undefined;


const count = useQuery(ctx, "SELECT count(*) FROM users", null, firstPick).data;
// count is a number


Pick the value of the first column of each row. Useful for queries that return a single column.

function pick<T extends any, R>(data: T[]): R[];


const names = useQuery(ctx, "SELECT name FROM users", null, pick).data;
// names is a string[]

Live Example

Below is a live notebook style example. You can modify code in any cell and press shift + enter to run it. Sharing variables between cells is done via provide and use statements. Given we're running everything natively in the browser (no babel or esbuild compilation step), we use htm (opens in a new tab) to write JSX-like syntax.

A cool thing about cr-sqlite is that you get cross-tab sync for free! Open this page in many tabs and interact with the todo widget at the bottom to check it out.

Let's import the cr-sqlite wasm bundle and create a database with a basic schema.

Now we'll write the react component for our todo list.

Lastly, we'll render the component to the page.