Offline Handling
Monitor network state and handle offline scenarios gracefully.
API Reference: useConnectionState · store.catchUp · store.networkEnabled
Connection State
Use useConnectionState() to monitor sync status:
import { observer, useConnectionState } from '@gluonic/client'
const SyncIndicator = observer(() => {
const {
isOnline, // Network available?
isSyncing, // Currently syncing?
queueLength, // Pending mutations
lastSync // Last successful sync time
} = useConnectionState()
if (!isOnline) {
return <Badge variant="warning">Offline</Badge>
}
if (isSyncing) {
return <Badge variant="info">Syncing...</Badge>
}
if (queueLength > 0) {
return <Badge variant="warning">{queueLength} pending</Badge>
}
return <Badge variant="success">Synced ✓</Badge>
})Network Detection
Gluonic tracks network state automatically:
// React Native
import NetInfo from '@react-native-community/netinfo'
// Gluonic integrates automatically
// Updates store.networkEnabled
// Web
// Uses navigator.onLine
// Updates store.networkEnabledQueue Management
View Pending Mutations
const PendingChanges = observer(() => {
const store = useStore()
const queue = store.storage.listTx() // Async, call in useEffect
return (
<div>
<h3>Pending Changes ({queue.length})</h3>
{queue.map(tx => (
<div key={tx.id}>
{tx.op} {tx.type}:{tx.modelId}
</div>
))}
</div>
)
})Clear Queue
// Clear all pending mutations (careful!)
await store.storage.clearTxQueue()
// Or clear specific transaction
await store.storage.dequeueTx(txId)Offline-First Patterns
Optimistic Actions
const LikeButton = observer(({ postId }) => {
const store = useStore()
const post = useModel<Post>('post', postId)
const handleLike = async () => {
// Works offline! Syncs when back online
await store.save('post', postId, {
likes: (post.likes || 0) + 1
})
}
return <button onClick={handleLike}>❤️ {post.likes}</button>
})Disable When Offline
const PublishButton = observer(({ post }) => {
const { isOnline } = useConnectionState()
const handlePublish = async () => {
await store.save('post', post.id, { published: true })
}
return (
<button
onClick={handlePublish}
disabled={!isOnline}
>
{isOnline ? 'Publish' : 'Offline - Cannot Publish'}
</button>
)
})Show Offline Banner
const App = observer(() => {
const { isOnline, queueLength } = useConnectionState()
return (
<div>
{!isOnline && (
<Banner variant="warning">
You're offline. {queueLength} changes will sync when back online.
</Banner>
)}
<MainContent />
</div>
)
})Sync Control
Manual Sync
const SyncButton = () => {
const store = useStore()
const handleSync = async () => {
await store.catchUp() // Delta sync + WebSocket reconnect
}
return <button onClick={handleSync}>Sync Now</button>
}Pause/Resume Sync
// Pause (e.g., to save battery)
store.networkEnabled = false
// Resume
store.networkEnabled = true
store.catchUp()Best Practices
DO ✅
- Show offline indicator subtly (small badge)
- Allow all operations offline
- Queue mutations for later sync
- Notify when back online
- Show pending changes count
DON’T ❌
- Block features when offline
- Show errors for offline state
- Clear local data on disconnect
- Require network for reads
- Disable UI when offline
Next Steps
- Offline-First Concept - Deep dive
- Queue Replay - How it works
- Examples - See it in action
Last updated on