@livestore/adapter-expo runs LiveStore in Expo and React Native applications. It persists data using expo-sqlite SQLite databases on the device filesystem and supports optional sync backends for multi-device synchronization.
Requirements
- React Native New Architecture (Fabric / TurboModules) must be enabled
- Expo SDK 51 or later is recommended
The Expo adapter requires the New Architecture. If your app runs on the Old Architecture, LiveStore will throw an error at startup with a link to the Expo migration guide.
Installation
npm install @livestore/adapter-expo
pnpm add @livestore/adapter-expo
yarn add @livestore/adapter-expo
You also need the Expo SQLite and Application packages:
npx expo install expo-sqlite expo-application
Exports
import { makePersistedAdapter } from '@livestore/adapter-expo'
makePersistedAdapter
Creates a persisted LiveStore adapter for Expo/React Native. Data is stored in SQLite databases on the device filesystem and survives app restarts.
function makePersistedAdapter(options?: MakeDbOptions): Adapter
Parameters
Optional sync backend for multi-device synchronization.sync: {
backend: makeWsSync({ url: 'wss://sync.example.com' })
}
options.storage.directory
The base directory for database files. Defaults to SQLite.defaultDatabaseDirectory.
options.storage.subDirectory
Sub-directory relative to storage.directory. Useful for namespacing multiple apps sharing the same SQLite directory.Example: with subDirectory: 'my-app', the resulting path would be:/data/.../SQLite/my-app/{storeId}/livestore-eventlog@3.db
Stable device identifier. Defaults to the Android ID or iOS Vendor ID provided by expo-application.
Session identifier within this device.
Deletes both the app database and event log on startup. Use only during development.
Example
import { makePersistedAdapter } from '@livestore/adapter-expo'
import { makeWsSync } from '@livestore/sync-cf/client'
export const adapter = makePersistedAdapter({
sync: {
backend: makeWsSync({ url: 'wss://sync.example.com' }),
},
storage: {
subDirectory: 'my-app',
},
})
Minimal setup without sync:
import { makePersistedAdapter } from '@livestore/adapter-expo'
export const adapter = makePersistedAdapter()
Using with React
Pass the adapter to storeOptions and wrap your app with StoreRegistryProvider:
import React, { Suspense } from 'react'
import { StoreRegistry } from '@livestore/livestore'
import { StoreRegistryProvider, useStore } from '@livestore/react'
import { unstable_batchedUpdates as batchUpdates } from 'react-native'
import { makePersistedAdapter } from '@livestore/adapter-expo'
import { storeOptions } from '@livestore/livestore'
import { schema } from './schema'
const adapter = makePersistedAdapter()
const myStoreOptions = storeOptions({ schema, adapter, storeId: 'my-app' })
const storeRegistry = new StoreRegistry({ defaultOptions: { batchUpdates } })
function App() {
return (
<StoreRegistryProvider storeRegistry={storeRegistry}>
<Suspense fallback={null}>
<TodoList />
</Suspense>
</StoreRegistryProvider>
)
}
function TodoList() {
const store = useStore(myStoreOptions)
const todos = store.useQuery(queryDb(tables.todos.query))
return todos.map((todo) => <Text key={todo.id}>{todo.text}</Text>)
}
Set EXPO_PUBLIC_LIVESTORE_DEVTOOLS_URL to connect the adapter to the LiveStore DevTools server. The adapter resolves the correct WebSocket URL automatically based on the Expo dev server host:
EXPO_PUBLIC_LIVESTORE_DEVTOOLS_URL=ws://0.0.0.0:4242
Peer dependencies
| Package | Version |
|---|
expo-sqlite | SDK 51+ |
expo-application | SDK 51+ |
effect | ^3.19.19 |