@@ -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
176169interface Task {
177170 id: string ;
@@ -180,50 +173,62 @@ interface Task {
180173}
181174
182175function 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
441494Configuration for adaptive polling behavior (polling mode only).
0 commit comments