React Native Database
If you are looking for a React Native Database, you usually want three things:
- Persistence: Store data locally on the device so the app works offline.
- Reactivity: Automatically update the UI when data changes.
- 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.
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-sqliteConfiguration:
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?
| Feature | AsyncStorage | SQLite (Raw) | Realm | Firestore (SDK) | |
|---|---|---|---|---|---|
| Type | Key-Value Store | Relational (SQL) | Object Store | Cloud Document Store | NoSQL 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.