Skip to main content

React Native Database

React Native provides a cross-platform JavaScript runtime that runs on different operating systems like Android, iOS, Windows and others. Mostly it is used to create hybrid Apps that run on mobile devices at Android (Google) and iOS (Apple).

In difference to the JavaScript runtime of browsers, React Native does not support all HTML5 APIs and so it is not possible to use browser storage possibilities like localstorage, cookies, WebSQL or IndexedDB. Instead a different storage solution must be chosen that does not come directly with React Native itself but has to be installed as a library or plugin.

React Native

Database Solutions for React-Native​

There are multiple database solutions that can be used with React Native. While I would recommend to use RxDB for most use cases, it is still helpful to learn about other alternatives.

RxDB

AsyncStorage​

AsyncStorage is a key->value storage solution that works similar to the browsers localstorage API. The big difference is that access to the AsyncStorage is not a blocking operation but instead everything is Promise based. This is a big benefit because long running writes and reads will not block your JavaScript process which would cause a laggy user interface.

/**
* Because it is Promise-based,
* you have to 'await' the call to getItem()
*/
await setItem('myKey', 'myValue');
const value = await AsyncStorage.getItem('myKey');

AsyncStorage was originally included in React Native itself. But it was deprecated by the React Native Team which recommends to use a community based package instead. There is a community fork of AsyncStorage that is actively maintained and open source.

AsyncStorage is fine when only a small amount of data needs to be stored and when no query capabilities besides the key-access are required. Complex queries or features are not supported which makes AsyncStorage not suitable for anything more than storing simple user settings data.

SQLite​

SQLite

SQLite is a SQL based relational database written in C that was crafted to be embed inside of applications. Operations are written in the SQL query language and SQLite generally follows the PostgreSQL syntax.

To use SQLite in React Native, you first have to include the SQLite library itself as a plugin. There a different project out there that can be used, but I would recommend to use the react-native-quick-sqlite project.

First you have to install the library into your React Native project via npm install react-native-quick-sqlite. In your code you can then import the library and create a database connection:

import {open} from 'react-native-quick-sqlite';
const db = open('myDb.sqlite');

Notice that SQLite is a file based database where all data is stored directly in the filesystem of the OS. Therefore to create a connection, you have to provide a filename.

With the open connection you can then run SQL queries:

let { rows } = db.execute('SELECT somevalue FROM sometable');

If that does not work for you, you might want to try the react-native-sqlite-storage project instead which is also very popular.

Downsides of Using SQLite in UI-Based Apps​

While SQLite is reliable and well-tested, it has several shortcomings when it comes to using it directly in UI-based React Native applications:

  • Lack of Observability: Out of the box, SQLite does not offer a straightforward way to observe queries or document fields. This means that implementing real-time data updates in your UI requires additional layers or libraries.
  • Bridging Overhead: Each query or data operation must go through the React Native bridge to access the native SQLite module. This can introduce performance bottlenecks or responsiveness issues, especially for large or complex data operations.
  • No Built-In Replication: SQLite on its own is not designed for syncing data across multiple devices or with a backend. If your app requires multi-device data syncing or offline-first features, additional tools or a custom solution are necessary.
  • Version Management: Handling schema changes often requires a custom migration process. If your data structure evolves frequently, managing these migrations can be cumbersome.

Overall, SQLite can be a good solution for straightforward, local-only data storage where complex real-time features or synchronization are not needed. For more advanced requirements, like reactive UI updates or multi-client data replication, you'll likely want a more feature-rich solution.

PouchDB​

PouchDB

PouchDB is a JavaScript NoSQL database that follows the API of the Apache CouchDB server database. The core feature of PouchDB is the ability to do a two-way replication with any CouchDB compliant endpoint. While PouchDB is pretty mature, it has some drawbacks that blocks it from being used in a client-side React Native application. For example it has to store all documents states over time which is required to replicate with CouchDB. Also it is not easily possible to fully purge documents and so it will fill up disc space over time. A big problem is also that PouchDB is not really maintained and major bugs like wrong query results are not fixed anymore. The performance of PouchDB is a general bottleneck which is caused by how it has to store and fetch documents while being compliant to CouchDB. The only real reason to use PouchDB in React Native, is when you want to replicate with a CouchDB or Couchbase server.

Because PouchDB is based on an adapter system for storage, there are two options to use it with React Native:

Because the asyncstorage adapter is no longer maintained, it is recommended to use the native-sqlite adapter:

First you have to install the adapter and other dependencies via npm install pouchdb-adapter-react-native-sqlite react-native-quick-sqlite react-native-quick-websql.

Then you have to craft a custom PouchDB class that combines these plugins:

import 'react-native-get-random-values';
import PouchDB from 'pouchdb-core';
import HttpPouch from 'pouchdb-adapter-http';
import replication from 'pouchdb-replication';
import mapreduce from 'pouchdb-mapreduce';
import SQLiteAdapterFactory from 'pouchdb-adapter-react-native-sqlite';
import WebSQLite from 'react-native-quick-websql';

const SQLiteAdapter = SQLiteAdapterFactory(WebSQLite);
export default PouchDB.plugin(HttpPouch)
.plugin(replication)
.plugin(mapreduce)
.plugin(SQLiteAdapter);

This can then be used to create a PouchDB database instance which can store and query documents:

const db = new PouchDB('mydb.db', {
adapter: 'react-native-sqlite'
});

RxDB​

RxDB

RxDB is an local-first, NoSQL-database for JavaScript applications. It is reactive which means that you can not only query the current state, but subscribe to all state changes like the result of a query or even a single field of a document. This is great for UI-based realtime applications in a way that makes it easy to develop realtime applications like what you need in React Native.

Key benefits of RxDB include:

  • Observability and Real-Time Queries: Automatic UI updates when underlying data changes, making it much simpler to build responsive, reactive apps.
  • Offline-First and Sync: Built-in support for syncing with CouchDB, or via GraphQL replication, allowing your app to work offline and seamlessly sync when online. It is easy to make the RxDB replication compatible with anything that supports HTTP.
  • Encryption and Data Security: RxDB supports field-level encryption and a robust plugin ecosystem for compression and attachments.
  • Data Modeling and Ease of Use: Offers a schema-based approach that helps catch invalid data early and ensures consistency.
  • Performance: Optimized for storing and querying large amounts of data on mobile devices.

There are multiple ways to use RxDB in React Native:

It is recommended to use the SQLite RxStorage because it has the best performance and is the easiest to set up. However it is part of the 👑 Premium Plugins which must be purchased, so to try out RxDB with React Native, you might want to use the memory storage first. Later you can replace it with the SQLite storage by just changing two lines of configuration.

First you have to install all dependencies via npm install rxdb rxjs rxdb-premium react-native-quick-sqlite. Then you can assemble the RxStorage and create a database with it:

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

// create database
const myRxDatabase = await createRxDatabase({
// Instead of a simple name,
// you can use a folder path to determine the database location
name: 'exampledb',
multiInstance: false, // <- Set this to false when using RxDB in React Native
storage: getRxStorageSQLite({
sqliteBasics: getSQLiteBasicsQuickSQLite(open)
})
});

// create collections
const collections = await myRxDatabase.addCollections({
humans: {
/* ... */
}
});

// insert document
await collections.humans.insert({id: 'foo', name: 'bar'});

// run a query
const result = await collections.humans.find({
selector: {
name: 'bar'
}
}).exec();

// observe a query
await collections.humans.find({
selector: {
name: 'bar'
}
}).$.subscribe(result => {/* ... */});

Using the SQLite RxStorage is pretty fast, which is shown in the performance comparison. To learn more about using RxDB with React Native, you might want to check out this example project.

Also RxDB provides many other features like encryption or compression. You can even store binary data as attachments or use RxDB as an ORM in React Native.

Realm​

MongoDB Realm

Realm is another database solution that is particularly popular in the mobile world. Originally an independent project, Realm is now owned by MongoDB, and has seen deeper integration with MongoDB services over time.

Pros:

  • Fast, object-based database approach with an easy data model.
  • Historically known for good performance and a simple, user-friendly API.

Downsides:

  • Forced MongoDB Cloud Usage: Realm Sync is now tightly coupled with MongoDB Realm Cloud. If you want to use their full sync or advanced features, you are essentially locked into MongoDB's ecosystem, which can be a downside if you need on-premise or custom hosting.
  • Missing or Limited Features: While Realm covers many basic needs, some developers find that advanced queries or certain offline-first features are not as robust or flexible as other solutions.
  • Vendor Lock-In: If you rely heavily on Realm Sync, migrating away from MongoDB's cloud can be difficult because the sync logic and data format are tightly integrated.
  • Community Concerns: Since the MongoDB acquisition, some worry about Realm's open-source future and whether large changes or new features will remain community-friendly.

Although Realm can be a good solution when used purely as a local database, if you plan on syncing data across clients or want to avoid cloud vendor lock-in, you should consider carefully how MongoDB's ownership might affect your long-term plans.

Firebase / Firestore​

Firebase

Firestore is a cloud based database technology that stores data on clients devices and replicates it with the Firebase cloud service that is run by google. It has many features like observability and authentication. The main feature lacking is the non-complete offline first support because clients cannot start the application while being offline because then the authentication does not work. After they are authenticated, being offline is no longer a problem. Also using firestore creates a vendor lock-in because it is not possible to replicate with a custom self hosted backend.

To get started with Firestore in React Native, it is recommended to use the React Native Firebase open-source project.

Follow up​

✕