Back to Rxdb

React Native Database - Sync & Store Like a Pro

docs/react-native-database.md

17.1.08.2 KB
Original Source

React Native Database - Sync & Store Like a Pro

The ultimate React Native Database guide. Build offline-first, real-time apps with RxDB. SQLite storage, easy sync, and React hooks included.

import {Steps} from '@site/src/components/steps'; import {Tabs} from '@site/src/components/tabs';

React Native Database

If you are looking for a React Native Database, you usually want three things:

  1. Persistence: Store data locally on the device so the app works offline.
  2. Reactivity: Automatically update the UI when data changes.
  3. Sync: Replicate data with a backend server in real-time.

RxDB covers all of these requirements out of the box. It is a local-first NoSQL database that runs deeply integrated with React Native, giving you the power of a full featured database engine inside your mobile app.

<center> </center>

The Storage Layer

React Native does not have a native database engine. To store data persistently and efficiently, RxDB offers multiple powerful options.

👑 Expo Filesystem (Highest Performance)

For the absolute best performance in React Native and Expo applications, the premium Expo Filesystem RxStorage is highly recommended. Built on expo-opfs, it completely bypasses the React Native bridge and delivers significantly faster read/write speeds than traditional SQLite.

SQLite

If you prefer a free solution or specifically need SQLite, RxDB fully supports SQLite. It works on all mobile platforms and abstracts the complex SQL commands into a simple, NoSQL JSON document API.

Depending on your environment, different SQLite adapters are recommended:

<Tabs>

React Native CLI

For bare React Native projects, use react-native-quick-sqlite. It uses JSI (JavaScript Interface) to communicate directly with C++, effectively bypassing the slow React Native Bridge.

Installation:

bash
npm install rxdb rxjs react-native-quick-sqlite

Configuration:

ts
import { createRxDatabase } from 'rxdb';
import {
    getRxStorageSQLite,
    getSQLiteBasicsQuickSQLite
} from 'rxdb-premium/plugins/storage-sqlite';
import { open } from 'react-native-quick-sqlite';

const db = await createRxDatabase({
    name: 'mydatabase',
    storage: getRxStorageSQLite({
        sqliteBasics: getSQLiteBasicsQuickSQLite(open)
    }),
    multiInstance: false,
    ignoreDuplicate: true
});

Expo Go

If you are using Expo, use the official expo-sqlite module.

Installation:

bash
npx expo install expo-sqlite
npm install rxdb rxjs

Configuration:

ts
import { createRxDatabase } from 'rxdb';
import {
    getRxStorageSQLite,
    getSQLiteBasicsExpoSQLiteAsync
} from 'rxdb-premium/plugins/storage-sqlite';
import * as SQLite from 'expo-sqlite';

const db = await createRxDatabase({
    name: 'mydatabase',
    storage: getRxStorageSQLite({
        sqliteBasics: getSQLiteBasicsExpoSQLiteAsync(SQLite.openDatabaseAsync)
    }),
    multiInstance: false,
    ignoreDuplicate: true
});
</Tabs>

React Integration

RxDB is deeply integrated with React. It provides hooks that make fetching data and subscribing to changes effortless.

<Steps>

1. Provide the Database

Wrap your application with the RxDatabaseProvider.

tsx
import { RxDatabaseProvider } from 'rxdb/plugins/react';

export default function App() {
  // ... create db instance
  return (
    <RxDatabaseProvider database={db}>
       <MyComponent />
    </RxDatabaseProvider>
  );
}

2. Observe Data

Use the useRxQuery hook (or useLiveRxQuery shortcut) to fetch data. The component will automatically re-render whenever the data in the database changes. You don't need to manually subscriptions or handling event listeners.

tsx
import { useRxCollection, useLiveRxQuery } from 'rxdb/plugins/react';

function TaskList() {
  const collection = useRxCollection('tasks');
  
  // This hook automatically updates 'tasks' whenever the query result changes
  const { result: tasks } = useLiveRxQuery(
    collection.find({
        selector: {
            done: { $eq: false }
        },
        sort: [{ createdAt: 'asc' }]
    })
  );

  return (
    <FlatList
      data={tasks}
      renderItem={({ item }) => <Text>{item.title}</Text>}
      keyExtractor={item => item.id}
    />
  );
}

3. Signals (Performance Mode)

For high-performance applications with frequent data updates, re-rendering the entire React component might be too slow. RxDB supports Signals (via @preact/signals-react or similar) to pinpoint updates directly to the DOM nodes.

tsx
// Enable the signals plugin once
import { addRxPlugin } from 'rxdb';
import {
    RxDBReactivityPreactSignalsPlugin
} from 'rxdb/plugins/reactivity-preact-signals';
addRxPlugin(RxDBReactivityPreactSignalsPlugin);

// ... in your component
const signals = collection.find().$$; // Returns a Signal<Doc[]>

Using signals allows you to update only the specific text node that changed, keeping your UI running at 60fps even with massive data flux.

</Steps>

Sync with Backend

A local database is useful, but a synchronized database is powerful. RxDB provides a robust replication protocol that can sync with any backend.

It has dedicated plugins for popular backend solutions:

For custom backends, you can implement the simple HTTP replication protocol.

Example: Sync with Supabase

Syncing is set-and-forget. You start the replication, and RxDB handles the rest (pulling changes, pushing writes, handling conflict resolution).

ts
import { replicateSupabase } from 'rxdb/plugins/replication-supabase';

const replicationState = replicateSupabase({
    replicationIdentifier: 'my-sync',
    collection: db.tasks,
    supabaseClient: supabase,
    pull: {},
    push: {},
});

Because RxDB handles the sync layer, you can build your app as if it were a purely local application. All reads and writes happen against the local SQLite database instantly, while the replication happens in the background. This is the essence of Local-First development.

Comparison with Alternatives

How does RxDB compare to other React Native database solutions?

FeatureAsyncStorageSQLite (Raw)RealmFirestore (SDK)RxDB
TypeKey-Value StoreRelational (SQL)Object StoreCloud Document StoreNoSQL Document Store
Reactivity❌ None❌ Manual events✅ Local listeners✅ Real-time listenersHooks / Signals / RxJS
Persistence✅ File (Slow)✅ File (Generic)✅ Custom File⚠️ Partial CacheSQLite / File
Sync❌ Manual❌ Manual✅ Realm Sync only✅ Firebase onlyAny Backend
Query Engine❌ None✅ SQL Strings✅ Custom API✅ LimitedMango JSON Query
Schema❌ None✅ SQL Schema✅ Class Schema❌ LooseJSON Schema
Migration❌ Manual❌ Manual SQL✅ Migration API❌ NoneAutomatic

Summary

  • AsyncStorage: Good for simple key-value pairs (like settings). Too slow for data.
  • SQLite: Great foundation, but requires writing raw SQL and manual reactivity/sync.
  • Realm: Fast object store, but locks you into the MongoDB ecosystem for sync. Realm was deprecated in 2024 (source).
  • Firestore: Easy networked DB, but poor offline support (cannot start offline) and latency issues.
  • RxDB: Combines the performance of local SQLite with the ease of NoSQL, automatic reactivity, and backend-agnostic synchronization.

Ready to start? Check out the React Native Example Project or read the Quickstart Guide.