Table of contents
1.
Introduction
2.
What is Realm?
2.1.
Key Features of Realm
2.2.
Getting Started with Realm
3.
To-Do App using Realm and React Native
3.1.
Import Statements
3.2.
Task Schema Definition
3.3.
AppWrapper Component
3.4.
TaskApp Component
3.5.
SafeAreaView and Styling
4.
Realm v/s SQLite
5.
Realm Database Internals
6.
Frequently Asked Questions
6.1.
What is the difference between FlatList and ScrollView?
6.2.
What are static class members?
6.3.
What are atomic operations in a database?
7.
Conclusion
Last Updated: Mar 27, 2024
Easy

Realm for React Native

Author Abhinav Anand
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Realm is a mobile database designed to simplify the process of building real-time and offline-first cross-platform applications. It supports multiple languages and frameworks such as React Native, Flutter, Kotlin, etc.

realm for react native

In this article, you will learn about Realm, its features, and how to use it in a project.

Let’s get started.

What is Realm?

Realm is a cross-platform mobile database that simplifies the process of building and managing local data storage in cross-platform mobile applications. It provides an alternative to traditional relational databases like SQLite.

Key Features of Realm

Realm supports the following features:-

  • Queries: You can query data from Realm using platform-native queries or with a raw platform-independent query language.
     
  • Encryption: Realm provides data encryption options that help you secure sensitive information stored within the database.
     
  • Indexes: In Realm, you can define indexes on specific fields of your data models. These fields are usually the ones you query frequently.
     
  • Reactivity: Realm uses reactive programming principles, which means that the changes in data are automatically reflected in the UI without requiring explicit updates.
     
  • Transactions: Realm guarantees that transactions are ACID-compliant. This means that all committed write operations are guaranteed to be valid.
     
  • Auto-Updates: Realm automatically updates the database to newer schema versions, reducing the need for manual data migration.

Getting Started with Realm

To add Realm to an existing React Native project, run the following command in your project directory:-

npm install realm @realm/react

 

Now that you know about Realm's features, let’s build a simple cross-platform To-Do app using it.

Also see,  React Native Reanimated

To-Do App using Realm and React Native

Before getting started, ensure you have an Android or iOS emulator set up in your system along with the latest version of NPM.

To create a new React Native project, run the following command in your terminal:-

npx create-expo-app

 

If everything goes well, you will see an output similar to the following:-

output

Next, we will navigate to the project directory and install all the necessary dependencies for using Realm.

cd ./Realm-ToDo
npm i realm @realm/react expo-dev-client
npm i @realm/babel-plugin --save-dev

 

Once all of the dependencies are installed, copy and paste the following into the App.js file.

import React, { useState } from "react";

import { SafeAreaView, View, Text, TextInput, FlatList, Pressable } from "react-native";

import { Realm, RealmProvider, useRealm, useQuery } from '@realm/react'



class Task extends Realm.Object {

  static generate(description) {

    return {

      _id: new Realm.BSON.ObjectId(),

      description,

      createdAt: new Date(),

    };

  }



  static schema = {

    name: 'Task',

    primaryKey: '_id',

    properties: {

      _id: 'objectId',

      description: 'string',

      isComplete: { type: 'bool', default: false },

      createdAt: 'date'

    },

  };

}



export default function AppWrapper() {

  return (

    <RealmProvider schema={[Task]}><TaskApp /></RealmProvider>

  )

}



function TaskApp() {

  const realm = useRealm();

  const tasks = useQuery(Task);

  const [newDescription, setNewDescription] = useState("")



  return (

    <SafeAreaView>

      <View style={{ flexDirection: 'row', justifyContent: 'center', margin: 100 }}>

        <TextInput

          value={newDescription}

          placeholder="Enter new task description"

          onChangeText={setNewDescription}

        />

        <Pressable

          onPress={() => {

            realm.write(() => {

              realm.create("Task", Task.generate(newDescription));

            });

            setNewDescription("")

          }}><Text>➕</Text></Pressable>

      </View>

      <FlatList data={tasks.sorted("createdAt")} keyExtractor={(item) => item._id.toHexString()} renderItem={({ item }) => {

        return (

          <View style={{ flexDirection: 'row', justifyContent: 'center', margin: 10 }}>

            <Pressable

              onPress={() =>

                realm.write(() => {

                  item.isComplete = !item.isComplete

                })

              }><Text>{item.isComplete ? "✅" : "☑️"}</Text></Pressable>

            <Text style={{ paddingHorizontal: 10 }} >{item.description}</Text>

            <Pressable

              onPress={() => {

                realm.write(() => {

                  realm.delete(item)

                })

              }} ><Text>{"🗑️"}</Text></Pressable>

          </View>

        );

      }} ></FlatList>

    </SafeAreaView >

  );

}

 

Now, run the following command in the project directory to launch the Android emulator.

npx expo run:android

 

This command generates a development build for your app and runs it in the Android emulator.

Results:

app screenshot
app screenshot

Let us take a closer look at how the code works.

Import Statements

We first import all the necessary components and functions from react, react-native, and the @realm/react library.

Task Schema Definition

The Task class extends Realm.Object, which means that instances of this class will be managed by the Realm database. It has the following class members:-

  • generate(description) function: This static method generates a new task object with the provided description.
     
  • schema: This defines the schema for the Task object. It specifies the name, primary key, and data types of the properties.

AppWrapper Component

This is the entry point for our app, and it wraps the TaskApp component with the RealmProvider, which allows the TaskApp component to use the hooks provided by the @realm/react library.

TaskApp Component

This is the component that defines the main functionality of our app. We use the following hooks inside it:-

  • useRealm: This custom hook provided by the @realm/react library returns an instance of the Realm database.
     
  • useQuery: Another custom hook provided by @realm/react to perform queries on the database. In this case, it fetches all Task objects.
     
  • useState: This hook provided by React allows us to maintain the state of a description that the user types into the input field.
     

We also use the following React Native components:-

  • TextInput: This component allows the user to enter a new task description.
     
  • Pressable: This component acts as a button for adding a new task to the list.
     
  • FlatList: This component efficiently renders lists of items in a React Native application. We use it for displaying the list of tasks.
     

We are using the realm.write() transaction for adding and removing tasks from the user's to-do list. This ensures that the changes are atomic and the database remains consistent.

SafeAreaView and Styling

The components are wrapped in a SafeAreaView to ensure that content is within the safe area of the device's screen. Styling is applied using inline style props to position and format UI elements.

In the next section, we will look at some differences between Realm and SQLite, a commonly used alternative to Realm.

Realm v/s SQLite

The following are crucial differences between Realm and SQLite:-

Feature Realm SQLite
Data Model It uses an object-oriented model with classes, offering a more intuitive data representation. Uses a relational data model with tables, columns, and rows, requiring schema definitions.
Performance It has efficient read and write operations that are optimized for mobile devices. It performs well but involves overhead due to SQL queries and ORM libraries.
Synchronization It offers built-in real-time data synchronization. Lacks built-in real-time capabilities.
Schema Changes Allows dynamic changes to the schema without complex migrations. Schema changes usually require manual migrations.
Reactive Programming It has a reactive programming model that automatically updates UI components when data changes. Reactive programming needs to be implemented separately using additional libraries for UI updates.

The choice between Realm and traditional mobile database solutions, such as SQLite, depends on the requirements of your project. 

In the next section, we will take a look at the internals of Realm.

Realm Database Internals

Instead of building on top of an existing database engine like SQLite, Realm was written from scratch in C++. Realm’s underlying storage layer uses B+ trees to organize objects, and as a result, it has control over all the optimizations from the storage level to the access level. In Realm, data is stored in collections of heterogeneous realm objects, which is equivalent to a row in a SQL database or a MongoDB document.

It uses several kings of files for storing the data on device storage, some of them are listed below:-

  • realm files: These files are suffixed with the .realm extension and they contain object data.
     
  • lock files: These are suffixed with the .realm.lock extension and they keep track of the versions of actively used data in Realm. This prevents Realm from reclaiming storage space that is still being used by a client application.
     
  • note files: These are suffixed with the .realm.note extension and they are used for inter-thread and inter-process notifications.
     

Realm uses the copy-on-write technique, which copies data to a new location on disk for every write operation instead of overwriting older data on disk. Upon a successful write operation, the database updates existing references to that data, and the older data is garbage collected when it is no longer actively used (tracked by note files).

Frequently Asked Questions

What is the difference between FlatList and ScrollView?

FlatList renders only those items that are currently visible to the user, and this makes it highly efficient for large datasets. ScrollView, on the other hand, renders all the elements at once, which can lead to performance issues.

What are static class members?

Static class members are properties or methods that belong to a class itself and not its instances. They're accessed via the class name, shared across all instances, and used for common functionalities.

What are atomic operations in a database?

Atomic operations in a database are indivisible actions that either fully succeed or entirely fail, ensuring data integrity and consistency even in the presence of errors or system failures.

Conclusion

In this article, you learned about Realm, a mobile database solution commonly used to develop cross-platform, offline-first applications. We looked at some of its features and compared it to SQLite, which is an alternative to Realm. We also built a basic To-Do list application using React Native and Realm.

Read the following articles to learn more about React Native:-

Happy Learning!

Live masterclass