React
To get started with React quickly, scaffold a new project with npm create @vlcn.io@latest 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 @vlcn.io/react (opens in a new tab) package and centers around:
- A
useQuery
hook that allows you to subscribe to a query and get the data in your component. - A DBProvider (opens in a new tab) to provide one or more databases to your component tree and kick off sync.
Installation
Install:
> npm install @vlcn.io/react @vlcn.io/rx-tbl
Import:
import { useQuery } from "@vlcn.io/react";
import tblrx from "@vlcn.io/rx-tbl";
API
useQuery
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;
Params:
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)
Usage:
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 (
<ul>
{data.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
first
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;
Usage:
const countRow = useQuery(ctx, "SELECT count(*) as c FROM users", null, first).data;
const count = countRow?.c;
firstPick
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;
Usage:
const count = useQuery(ctx, "SELECT count(*) FROM users", null, firstPick).data;
// count is a number
pick
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[];
Usage:
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.