Skip to main content

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.

RxDB

The Storage Layer: SQLiteโ€‹

React Native does not have a native database engine. To store data persistently and efficiently, RxDB uses SQLite under the hood. SQLite is available on all mobile platforms (iOS, Android) and offers great performance.

RxDB abstracts the complex SQL commands away and provides a simple, NoSQL JSON document API that is easy to use for JavaScript developers.

We recommend different SQLite adapters depending on your environment:

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:

npm install rxdb rxjs react-native-quick-sqlite

Configuration:

import { createRxDatabase } from 'rxdb';
import { getRxStorageSQLite, getSQLiteBasicsQuickSQLite } from 'rxdb/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
});

React Integrationโ€‹

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

1. Provide the Databaseโ€‹

Wrap your application with the RxDatabaseProvider.

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.

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.

// 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.

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).

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 RxDB
TypeKey-Value StoreRelational (SQL)Object StoreCloud Document StoreNoSQL Document Store
ReactivityโŒ NoneโŒ Manual eventsโœ… Local listenersโœ… Real-time listenersโœ… Hooks / Signals / RxJS
Persistenceโœ… File (Slow)โœ… File (Generic)โœ… Custom Fileโš ๏ธ Partial Cacheโœ… SQLite / File
SyncโŒ ManualโŒ Manualโœ… Realm Sync onlyโœ… Firebase onlyโœ… Any Backend
Query EngineโŒ Noneโœ… SQL Stringsโœ… Custom APIโœ… Limitedโœ… Mango JSON Query
SchemaโŒ Noneโœ… SQL Schemaโœ… Class SchemaโŒ Looseโœ… JSON Schema
MigrationโŒ ManualโŒ Manual SQLโœ… Migration APIโŒ Noneโœ… Automatic

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.