@pylonsync/react-native brings the React hooks to mobile. Same API as @pylonsync/react plus:
- AsyncStorage-backed durable replica — the local sync replica survives app kills (via
AsyncStorageReplicaPersistence, enabled by default) - AsyncStorage bridge — auth tokens + client id persist correctly on iOS / Android
useNetworkStatushook for offline-aware UI- Foreground/background lifecycle handling — sync pauses when backgrounded, catches up on resume
Install
@react-native-async-storage/async-storage and @react-native-community/netinfo are peer dependencies. For Expo projects you’re done. For bare React Native, link the native modules per their docs.
Configure
Callinit() from @pylonsync/react-native once before your first hook. It bootstraps the AsyncStorage bridge (tokens + client id), installs the durable AsyncStorageReplicaPersistence, and starts sync:
init() reads existing pylon keys (pylon:<app>:client_id, pylon:<app>:token, etc.) into an in-memory cache and writes through to AsyncStorage. The sync engine’s storage interface is synchronous — the bridge keeps it that way without making your call sites async. Pass persist: false to skip the durable replica, or your own persistence adapter.
Use the React hooks
Same as web — use thedb.* namespace (it wires the global engine for you) and useSession(db.sync):
Offline persistence
The sync engine ships withIndexedDBPersistence for browsers; on RN you swap in the AsyncStorage-backed equivalent. init() already installs it by default — wire it manually only when you construct the engine yourself:
- The replica snapshot + cursor are persisted to AsyncStorage (durable across cold launches)
- The mutation queue is persisted (offline writes survive app kill)
- App startup hydrates from the persisted replica first, then catches up via pull
Network status
useNetworkStatus is for UI affordances.
Foreground / background
The engine listens forAppState changes:
- Background → pause WebSocket; mutations still queue locally
- Foreground → reconnect, pull missed changes, drain the queue
crdt-subscribe re-send the engine does on every reconnect, so binary CRDT frames keep arriving).
For long-lived background sync (e.g. push-notification-triggered fetch), use the standalone engine.pull() from your background task handler.
Higher-level offline store
For cases where you want a manual cache outside the sync engine (e.g. cache derived data, store user preferences):pylon: prefix.
Performance
- Use
FlatList/SectionListwithuseQueryresults — they re-render fully on every store change, so list virtualization matters. - Memoize derived data with
useMemoto avoid re-computing on every store notify. - Limit
useQueryresults — for large entities, useuseInfiniteQueryinstead so the screen doesn’t render thousands of rows. - Backgrounded sync uses zero CPU — the engine pauses cleanly.
Push notifications
Pylon doesn’t ship a push provider — use Expo Push, Firebase, OneSignal, or APNs/FCM directly. Pattern:- On sign-in, register the device token with your Pylon backend (
POST /api/fn/registerPushToken). - In your function/cron, push when something interesting happens.
- On notification tap, foreground the app — the sync engine catches up automatically.
Tested combinations
- Expo SDK 50+
- React Native 0.74+ (peer-dependency floor)
- New Architecture (Fabric / TurboModules) — works
- Hermes JS engine — works (no Loro CRDT WASM dependency in this package)
- Bare React Native — works after manual native module linking
Differences from web React
The hooks and call signatures are identical.