Skip to content

Commit d9ac5d8

Browse files
committed
docs: update readme
1 parent 5af1a5e commit d9ac5d8

File tree

1 file changed

+103
-50
lines changed

1 file changed

+103
-50
lines changed

README.md

Lines changed: 103 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -159,19 +159,12 @@ export default function App() {
159159
}
160160
```
161161

162-
### 3. Use the Hooks
162+
### 3. Read Data
163163

164-
The library provides specialized hooks to simplify querying, syncing, and state management.
164+
Use `useSqliteSyncQuery` to run a reactive query that automatically updates when the table changes — no manual refresh needed.
165165

166166
```typescript
167-
import { useCallback } from 'react';
168-
import {
169-
useSqliteSyncQuery,
170-
useOnTableUpdate,
171-
useTriggerSqliteSync,
172-
useSqliteTransaction,
173-
useSyncStatus,
174-
} from '@sqliteai/sqlite-sync-react-native';
167+
import { useSqliteSyncQuery } from '@sqliteai/sqlite-sync-react-native';
175168

176169
interface Task {
177170
id: string;
@@ -180,50 +173,62 @@ interface Task {
180173
}
181174

182175
function TaskList() {
183-
// 1. REACTIVE QUERY: Automatically updates when table changes (via transactions)
184-
const {
185-
data: tasks,
186-
isLoading,
187-
error,
188-
} = useSqliteSyncQuery<Task>({
176+
const { data: tasks, isLoading, error } = useSqliteSyncQuery<Task>({
189177
query: 'SELECT * FROM tasks ORDER BY created_at DESC',
190178
arguments: [],
191179
fireOn: [{ table: 'tasks' }],
192180
});
193181

194-
// 2. ROW-LEVEL NOTIFICATIONS: Get notified of individual INSERT/UPDATE/DELETE
195-
useOnTableUpdate<Task>({
196-
tables: ['tasks'],
197-
onUpdate: (data) => {
198-
console.log(`Row ${data.operation}:`, data.row);
199-
},
200-
});
182+
if (isLoading) return <Text>Loading...</Text>;
183+
if (error) return <Text>Error: {error.message}</Text>;
184+
185+
return (
186+
<FlatList
187+
data={tasks}
188+
keyExtractor={(item) => item.id}
189+
renderItem={({ item }) => <Text>{item.title}</Text>}
190+
/>
191+
);
192+
}
193+
```
194+
195+
### 4. Write Data
201196
202-
// 3. WRITING DATA: Use transactions to trigger reactive queries
197+
Use `useSqliteTransaction` to insert or update rows. Transactions automatically trigger reactive queries to re-run.
198+
199+
```typescript
200+
import { useSqliteTransaction } from '@sqliteai/sqlite-sync-react-native';
201+
202+
function AddTaskButton() {
203203
const { executeTransaction } = useSqliteTransaction();
204-
const { triggerSync } = useTriggerSqliteSync();
205204

206-
// 4. SYNC STATUS: Get sync state for UI indicators
207-
const { isSyncing } = useSyncStatus();
205+
const addTask = async (title: string) => {
206+
await executeTransaction(async (tx) => {
207+
await tx.execute(
208+
'INSERT INTO tasks (id, title) VALUES (cloudsync_uuid(), ?);',
209+
[title]
210+
);
211+
});
212+
// The reactive query in TaskList updates automatically!
213+
};
208214

209-
const addTask = useCallback(
210-
async (title: string) => {
211-
// Use transaction to trigger reactive query update
212-
// Uses writeDb by default (no need to specify readOnly: false)
213-
await executeTransaction(async (tx) => {
214-
await tx.execute(
215-
'INSERT INTO tasks (id, title) VALUES (cloudsync_uuid(), ?);',
216-
[title]
217-
);
218-
});
219-
// Optional: Push changes to cloud immediately
220-
triggerSync();
221-
},
222-
[executeTransaction, triggerSync]
223-
);
215+
return <Button title="Add Task" onPress={() => addTask('New Task')} />;
216+
}
217+
```
224218
225-
if (isLoading) return <Text>Loading local DB...</Text>;
226-
if (error) return <Text>Error: {error.message}</Text>;
219+
### 5. Sync & Status
220+
221+
Use `useTriggerSqliteSync` to manually trigger a sync, and `useSyncStatus` to display sync state in your UI.
222+
223+
```typescript
224+
import {
225+
useTriggerSqliteSync,
226+
useSyncStatus,
227+
} from '@sqliteai/sqlite-sync-react-native';
228+
229+
function SyncControls() {
230+
const { triggerSync } = useTriggerSqliteSync();
231+
const { isSyncing, lastSyncTime, syncError } = useSyncStatus();
227232

228233
return (
229234
<View>
@@ -232,12 +237,10 @@ function TaskList() {
232237
onPress={triggerSync}
233238
disabled={isSyncing}
234239
/>
235-
236-
{tasks.map((task) => (
237-
<Text key={task.id}>{task.title}</Text>
238-
))}
239-
240-
<Button title="Add Task" onPress={() => addTask('New Task')} />
240+
{lastSyncTime && (
241+
<Text>Last sync: {new Date(lastSyncTime).toLocaleTimeString()}</Text>
242+
)}
243+
{syncError && <Text>Sync error: {syncError.message}</Text>}
241244
</View>
242245
);
243246
}
@@ -436,6 +439,56 @@ Use `onDatabaseReady` to run migrations or other setup after the database opens
436439
>
437440
```
438441

442+
#### Custom Push Permission UI with `onBeforePushPermissionRequest`
443+
444+
When using push mode, the system will prompt the user for notification permissions. Use `onBeforePushPermissionRequest` to show your own UI (e.g., an explanation modal) before the system prompt appears. Return `true` to proceed with the system prompt, or `false` to skip it.
445+
446+
```typescript
447+
import { useState, useCallback, useRef } from 'react';
448+
import { Modal, View, Text, TouchableOpacity } from 'react-native';
449+
450+
export default function App() {
451+
const [showDialog, setShowDialog] = useState(false);
452+
const resolverRef = useRef<((value: boolean) => void) | null>(null);
453+
454+
const handleBeforePermission = useCallback(async () => {
455+
return new Promise<boolean>((resolve) => {
456+
resolverRef.current = resolve;
457+
setShowDialog(true);
458+
});
459+
}, []);
460+
461+
return (
462+
<>
463+
<Modal visible={showDialog} transparent>
464+
<View style={{ flex: 1, justifyContent: 'center', padding: 24 }}>
465+
<Text>Enable notifications for real-time sync?</Text>
466+
<TouchableOpacity onPress={() => {
467+
setShowDialog(false);
468+
resolverRef.current?.(true); // Proceed to system prompt
469+
}}>
470+
<Text>Enable</Text>
471+
</TouchableOpacity>
472+
<TouchableOpacity onPress={() => {
473+
setShowDialog(false);
474+
resolverRef.current?.(false); // Skip, fall back to polling
475+
}}>
476+
<Text>Not Now</Text>
477+
</TouchableOpacity>
478+
</View>
479+
</Modal>
480+
<SQLiteSyncProvider
481+
syncMode="push"
482+
onBeforePushPermissionRequest={handleBeforePermission}
483+
// ...other props
484+
>
485+
<YourApp />
486+
</SQLiteSyncProvider>
487+
</>
488+
);
489+
}
490+
```
491+
439492
#### `AdaptivePollingConfig`
440493
441494
Configuration for adaptive polling behavior (polling mode only).

0 commit comments

Comments
 (0)