The configureObservableSync() function sets global defaults for all synced observables. This is useful for setting application-wide persistence plugins, retry behavior, and other common settings.
Usage
import { configureObservableSync } from '@legendapp/state/sync'
import { ObservablePersistLocalStorage } from '@legendapp/state/persist-plugins/local-storage'
configureObservableSync ({
persist: {
plugin: ObservablePersistLocalStorage
},
retry: {
infinite: true ,
delay: 1000
},
debounceSet: 500
})
Parameters
options
SyncedOptionsGlobal
required
Global configuration options for all synced observables
SyncedOptionsGlobal
Default persistence configuration Default persistence plugin (localStorage, IndexedDB, etc.) import { ObservablePersistLocalStorage } from '@legendapp/state/persist-plugins/local-storage'
persist : {
plugin : ObservablePersistLocalStorage
}
Retry failed remote syncs on next load. Useful for offline support.
If true, observables won’t persist changes by default
Global error handler for persistence get operations
Global error handler for persistence set operations
indexedDB
ObservablePersistIndexedDBPluginOptions
IndexedDB-specific configuration indexedDB : {
databaseName : 'myapp' ,
version : 1 ,
tableNames : [ 'users' , 'posts' , 'settings' ]
}
asyncStorage
ObservablePersistAsyncStoragePluginOptions
AsyncStorage-specific configuration (React Native) import AsyncStorage from '@react-native-async-storage/async-storage'
asyncStorage : {
AsyncStorage ,
preload : true // Preload all keys on startup
}
Default retry behavior for failed operations Retry indefinitely until successful
Maximum number of retry attempts (if not infinite)
Initial delay between retries in milliseconds
backoff
'constant' | 'exponential'
default: "constant"
How to increase delay between retries
constant: Same delay each time
exponential: Double delay each time
Maximum delay between retries (for exponential backoff)
Default debounce time in milliseconds for remote saves. Batches rapid changes together. debounceSet : 500 // Wait 500ms after last change before saving
syncMode
'auto' | 'manual'
default: "auto"
Default sync mode for all observables
auto: Sync automatically when accessed
manual: Only sync when sync() is called
mode
'set' | 'assign' | 'merge' | 'append' | 'prepend'
default: "set"
Default mode for applying remote data
onBeforeSet
(params: { cancel: boolean }) => void
Global handler called before any set operation
Global handler called after any set operation
onError
(error: Error, params: SyncedErrorParams) => void
Global error handler for all sync operations onError : ( error , { source , type , retry , revert }) => {
console . error ( `Error in ${ source } :` , error )
// Report to error tracking service
Sentry . captureException ( error )
}
Return Value
This function does not return a value. It modifies the global configuration.
Examples
Basic Configuration
import { configureObservableSync } from '@legendapp/state/sync'
import { ObservablePersistLocalStorage } from '@legendapp/state/persist-plugins/local-storage'
configureObservableSync ({
persist: {
plugin: ObservablePersistLocalStorage
}
})
// Now all synced observables use localStorage by default
const user$ = synced ({
get : () => api . getUser (),
persist: { name: 'user' } // No need to specify plugin
})
IndexedDB Configuration
import { configureObservableSync } from '@legendapp/state/sync'
import { ObservablePersistIndexedDB } from '@legendapp/state/persist-plugins/indexeddb'
configureObservableSync ({
persist: {
plugin: ObservablePersistIndexedDB ,
indexedDB: {
databaseName: 'myapp' ,
version: 1 ,
tableNames: [ 'users' , 'posts' , 'comments' , 'settings' ]
}
}
})
React Native with AsyncStorage
import { configureObservableSync } from '@legendapp/state/sync'
import { ObservablePersistAsyncStorage } from '@legendapp/state/persist-plugins/async-storage'
import AsyncStorage from '@react-native-async-storage/async-storage'
configureObservableSync ({
persist: {
plugin: ObservablePersistAsyncStorage ,
asyncStorage: {
AsyncStorage ,
preload: [ 'user' , 'settings' ] // Preload specific keys
}
}
})
Retry Configuration
configureObservableSync ({
retry: {
infinite: true , // Keep retrying
delay: 1000 , // Start with 1 second
backoff: 'exponential' , // Double each time
maxDelay: 30000 // Max 30 seconds between retries
},
persist: {
plugin: ObservablePersistLocalStorage ,
retrySync: true // Retry failed syncs on next load
}
})
Debounce Configuration
configureObservableSync ({
debounceSet: 1000 , // Wait 1 second after last change
persist: {
plugin: ObservablePersistLocalStorage
}
})
// Good for rapid user input
const search$ = synced ({
get : ( params ) => api . search ( params . value ),
persist: { name: 'search' }
// Inherits 1 second debounce
})
Global Error Handling
import * as Sentry from '@sentry/browser'
configureObservableSync ({
persist: {
plugin: ObservablePersistLocalStorage ,
onGetError : ( error ) => {
console . error ( 'Persistence load error:' , error )
Sentry . captureException ( error )
},
onSetError : ( error ) => {
console . error ( 'Persistence save error:' , error )
Sentry . captureException ( error )
}
},
onError : ( error , { source , type }) => {
console . error ( `Sync error in ${ source } ( ${ type } ):` , error )
Sentry . captureException ( error , {
tags: { source , type }
})
}
})
Manual Sync Mode
configureObservableSync ({
syncMode: 'manual' , // Don't sync automatically
persist: {
plugin: ObservablePersistLocalStorage
}
})
// All observables now require manual sync
const data$ = synced ({
get : () => api . getData (),
persist: { name: 'data' }
})
// Must call sync manually
const syncState = syncState ( data$ )
await syncState . sync ()
Offline-First Configuration
configureObservableSync ({
persist: {
plugin: ObservablePersistIndexedDB ,
retrySync: true , // Queue failed syncs
indexedDB: {
databaseName: 'myapp_offline' ,
version: 1 ,
tableNames: [ 'todos' , 'notes' ]
}
},
retry: {
infinite: true , // Keep trying to sync
delay: 5000 , // Try every 5 seconds
backoff: 'constant'
},
debounceSet: 2000 , // Batch changes
onError : ( error , { source }) => {
// Don't show errors for network failures
if ( error . message . includes ( 'fetch' )) return
showErrorToast ( ` ${ source } failed: ${ error . message } ` )
}
})
Per-Observable Override
Individual observables can override global settings:
// Global config
configureObservableSync ({
debounceSet: 500 ,
retry: { times: 3 }
})
// Override for specific observable
const data$ = synced ({
get : () => api . getData (),
debounceSet: 0 , // No debounce for this one
retry: { infinite: true } // Retry forever
})
Best Practices
Call early : Configure before creating any synced observables
Use appropriate plugin : localStorage for web, AsyncStorage/MMKV for React Native
Enable retry : Use retrySync: true for offline support
Set debounce : Use debounceSet to reduce server load
Handle errors : Implement onError for production apps
See Also