Skip to main content
@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
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

options.sync
SyncOptions
Optional sync backend for multi-device synchronization.
sync: {
  backend: makeWsSync({ url: 'wss://sync.example.com' })
}
options.storage.directory
string
The base directory for database files. Defaults to SQLite.defaultDatabaseDirectory.
options.storage.subDirectory
string
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
options.clientId
string
Stable device identifier. Defaults to the Android ID or iOS Vendor ID provided by expo-application.
options.sessionId
string
default:"'static'"
Session identifier within this device.
options.resetPersistence
boolean
default:"false"
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:
App.tsx
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>)
}

DevTools

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:
.env
EXPO_PUBLIC_LIVESTORE_DEVTOOLS_URL=ws://0.0.0.0:4242

Peer dependencies

PackageVersion
expo-sqliteSDK 51+
expo-applicationSDK 51+
effect^3.19.19

Build docs developers (and LLMs) love