Skip to content

Commit 20194d9

Browse files
authored
Implement useReactiveQuery hooks for React, Vue, and Angular (#93)
* Add useReactiveQuery for Angular * Add useReactiveQuery for Vue * Add useReactiveQuery for React * Fix React version of useReactiveQuery * Use SqlTag type in client too * Add status to useReactiveQuery * Document useReactiveQuery * Set allowSignalWrites for Angular 17 and 18 compatibility * Reset pending state when DB or query is changed * Add new headline features
1 parent c105867 commit 20194d9

File tree

10 files changed

+486
-91
lines changed

10 files changed

+486
-91
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ SQLocal makes it easy to run SQLite3 in the browser, backed by the origin privat
99
- 🔎 Locally executes any query that SQLite3 supports
1010
- 🧵 Runs the SQLite engine in a web worker so queries do not block the main thread
1111
- 📂 Persists data to the origin private file system, which is optimized for fast file I/O
12-
- 🔒 Each user can have their own private database instance
1312
- 🚀 Simple API; just name your database and start running SQL queries
13+
- ⚡️ Subscribe to query results and receive changes, even across tabs
14+
- 🔒 Each user can have their own private database instance
1415
- 🛠️ Works with Kysely and Drizzle ORM for making type-safe queries
16+
- 🤝 Get set up quickly with hooks for UI frameworks and a Vite plugin
1517

1618
## Examples
1719

docs/api/reactivequery.md

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const subscription = reactiveQuery(
2929
});
3030
```
3131

32-
The query can be any SQL statement that reads one or more tables. It can be passed using a `sql` tag function available in the `reactiveQuery` callback that works similarly to the [`sql` tag function used for single queries](sql.md). It can also be a query built with Drizzle or Kysely; see the "Query Builders" section below.
32+
The query can be any SQL statement that reads one or more tables. It can be passed using a `sql` tag function available in the `reactiveQuery` callback that works similarly to the [`sql` tag function used for single queries](sql.md). It can also be a query built with Drizzle or Kysely; see the "Query Builders" section [below](#query-builders).
3333

3434
You can then call `subscribe` on the object returned from `reactiveQuery` to register a callback that gets called an initial time and then again whenever the one or more of the queried tables are changed. The latest result data from the query will be passed as the first argument to your callback.
3535

@@ -85,3 +85,76 @@ const subscription = reactiveQuery(
8585
console.log('Grocery List Updated:', data);
8686
});
8787
```
88+
89+
## UI Frameworks
90+
91+
We also provide `useReactiveQuery` hook implementations to make it easier to integrate reactive queries with the reactivity systems of UI frameworks. The hook handles subscribing, returns reactive data, and automatically unsubscribes from the query when the component it's used in is destroyed.
92+
93+
`useReactiveQuery` takes your `SQLocal` instance and a SQL query as arguments. The query can be passed using the `sql` tag function or using a query builder as described [above](#query-builders). It returns an object containing the following reactive values:
94+
95+
- **`data`** (`Result[]`) - The result data from your SQL query.
96+
- **`error`** (`Error | undefined`) - An `Error` object if the SQL query fails.
97+
- **`status`** (`'pending' | 'error' | 'ok'`) - The string `'pending'` if the SQL query has not completed for the first time yet, `'error'` if the SQL query failed, or `'ok'` if the SQL query returned successfully.
98+
99+
### React
100+
101+
Import the React version of `useReactiveQuery` from `sqlocal/react`. It requires React 18 or higher.
102+
103+
In addition to `data`, `error`, and `status`, the object returned from this version of `useReactiveQuery` also contains `setDb` and `setQuery` functions which allow you to dynamically change the arguments from their initial values and automatically resubscribe.
104+
105+
```js
106+
import { SQLocal } from 'sqlocal';
107+
import { useReactiveQuery } from 'sqlocal/react';
108+
109+
const db = new SQLocal({
110+
databasePath: 'database.sqlite3',
111+
reactive: true,
112+
});
113+
114+
export function MyComponent() {
115+
const groceries = useReactiveQuery(db, (sql) => sql`SELECT * FROM groceries`);
116+
}
117+
```
118+
119+
### Vue
120+
121+
Import the Vue version of `useReactiveQuery` from `sqlocal/vue`. It requires Vue 3 or higher.
122+
123+
This version of `useReactiveQuery` returns `data`, `error`, and `status` as read-only Vue refs. It can also accept its arguments as refs, which allows you to dynamically change them from their initial values and automatically resubscribe.
124+
125+
```vue
126+
<script setup>
127+
import { SQLocal } from 'sqlocal';
128+
import { useReactiveQuery } from 'sqlocal/vue';
129+
130+
const db = new SQLocal({
131+
databasePath: 'database.sqlite3',
132+
reactive: true,
133+
});
134+
const groceries = useReactiveQuery(db, (sql) => sql`SELECT * FROM groceries`);
135+
</script>
136+
```
137+
138+
### Angular
139+
140+
Import the Angular version of `useReactiveQuery` from `sqlocal/angular`. It requires Angular 17 or higher.
141+
142+
This version of `useReactiveQuery` returns `data`, `error`, and `status` as read-only Angular signals. It can also accept its arguments as signals, which allows you to dynamically change them from their initial values and automatically resubscribe.
143+
144+
```ts
145+
import { Component } from '@angular/core';
146+
import { SQLocal } from 'sqlocal';
147+
import { useReactiveQuery } from 'sqlocal/angular';
148+
149+
const db = new SQLocal({
150+
databasePath: 'database.sqlite3',
151+
reactive: true,
152+
});
153+
154+
@Component({
155+
selector: 'my-component',
156+
})
157+
export class MyComponent {
158+
groceries = useReactiveQuery(db, (sql) => sql`SELECT * FROM groceries`);
159+
}
160+
```

docs/index.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,19 @@ features:
3131
- title: Persisted
3232
icon: 📂
3333
details: Persists data to the origin private file system, which is optimized for fast file I/O
34-
- title: Per-User
35-
icon: 🔒
36-
details: Each user can have their own private database instance
3734
- title: Simple API
3835
icon: 🚀
3936
details: Just name your database and start running SQL queries
37+
- title: Reactive
38+
icon: ⚡️
39+
details: Subscribe to query results and receive changes, even across tabs
40+
- title: Per-User
41+
icon: 🔒
42+
details: Each user can have their own private database instance
4043
- title: TypeScript
4144
icon: 🛠️
4245
details: Works with Kysely and Drizzle ORM for making type-safe queries
46+
- title: Integrations
47+
icon: 🤝
48+
details: Get set up quickly with hooks for UI frameworks and a Vite plugin
4349
---

0 commit comments

Comments
 (0)