This is not the current version. View the latest documentation

Realm React Native enables you to efficiently write your app’s model layer in a safe, persisted and fast way. Here’s what it looks like:

// Define your models and their properties
class Car {}
Car.schema = {
  name: 'Car',
  properties: {
    make:  'string',
    model: 'string',
    miles: 'int',
  }
};
class Person {}
Person.schema = {
  name: 'Person',
  properties: {
    name:    {type: 'string'},
    cars:    {type: 'list', objectType: 'Car'},
    picture: {type: 'data', optional: true}, // optional property
  }
};

// Get the default Realm with support for our objects
let realm = new Realm({schema: [Car, Person]});

// Create Realm objects and write to local storage
realm.write(() => {
  let myCar = realm.create('Car', {
    make: 'Honda',
    model: 'Civic',
    miles: 1000,
  });
  myCar.miles += 20; // Update a property value
});

// Query Realm for all cars with a high mileage
let cars = realm.objects('Car').filtered('miles > 1000');

// Will return a Results object with our 1 car
cars.length // => 1

// Add another car
realm.write(() => {
  let myCar = realm.create('Car', {
    make: 'Ford',
    model: 'Focus',
    miles: 2000,
  });

// Query results are updated in realtime
cars.length // => 2

Getting Started

Follow the installation instructions below to use Realm React Native via npm, or see the source on GitHub.

Prerequisites

  • Make sure your environment is set up to run react native applications. Follow the React Native instructions.
  • React Native 0.20.0 or later supported.
  • Apps using Realm can target both iOS & Android.

Installation

  • Create a new ReactNative project:

    react-native init <project-name>
  • Change directories into the new project (cd <project-name>) and add the realm dependency:

    npm install --save realm
  • Open the generated Xcode project (ios/<project-name>.xcodeproj)
  • Making sure the top-level project is selected in the sidebar, change the iOS Deployment Target to at least 8.0 in the project settings.
  • Right-click the Libraries group in the sidebar and click Add Files to “<project-name>”. Select ../node_modules/realm/RealmJS.xcodeproj from the dialog.
  • Open the General tab for your app’s Targets setting. In the left column, expand Libraries > RealmJS > Products and drag RealmReact.framework into the Embedded Binaries section in the General tab for your app’s target settings. See screenshot.
  • In the Build Phases tab for your app’s Targets settings, make sure RealmReact.framework is added to the Link Binary with Libraries build phase.
  • Create a new ReactNative project:

    react-native init <project-name>
  • Change directories into the new project (cd <project-name>) and add the realm dependency:

    npm install --save realm
  • Run this command from the project directory:

    react-native link realm
  • Open android/app/src/main/java/com/<project-name>/MainActivity.java and do the following:

    • Add import io.realm.react.RealmReactPackage; under the other imports.
    • Add new RealmReactPackage() to the list returned by the getPackages() method.


You’re now ready to go. To see Realm in action, add the following as the definition for your class <project-name> in index.ios.js or index.android.js:

const Realm = require('realm');

class <project-name> extends Component {
 render() {
   var realm = new Realm({schema:[{name:'Dog', properties:{name: 'string'%>]});
   realm.write(()=>{
     realm.create('Dog', ['Rex']);
   })
   return (
     <View style={styles.container}>
       <Text style={styles.welcome}>
         Count of Dogs in Realm: {realm.objects('Dog').length}
       </Text>
     </View>
   );
 }
}

You can then run your app on a device & simulator!

API Reference

You can consult our full API reference for all classes, methods and more.

Examples

Start by cloning the project from GitHub:

git clone https://github.com/realm/realm-js.git

Then in the cloned directory:

git submodule update --init --recursive

On android you need the NDK installed and to set the ANDROID_NDK environment variable:

export ANDROID_NDK=/usr/local/Cellar/android-ndk/r10e

The React Native examples are in the examples directory. You need to run npm install for each example before running for the first time.

Getting Help

  • Need help with your code? Ask on StackOverflow. We actively monitor & answer questions on SO!
  • Have a bug to report? Open an issue on our repo. If possible, include the version of Realm, a full log, the Realm file, and a project that shows the issue.
  • Have a feature request? Open an issue on our repo. Tell us what the feature should do, and why you want the feature.

If you’re using a crash reporter (like Crashlytics or HockeyApp), make sure to enable log collection. Realm logs metadata information (but no user data) when throwing exceptions and in irrecoverable situations, and these messages can help debug when things go wrong.

Models

Realm data models are defined by the schema information passed into a Realm during initialization. The schema for an object consists of the object’s name and a set of properties each of which has a name and type as well as the objectType for object and list properties. You can also designate each property to be optional or to have a default value.

var Realm = require('realm');

const CarSchema = {
  name: 'Car',
  properties: {
    make:  'string',
    model: 'string',
    miles: {type: 'int', default: 0},
  }
};
const PersonSchema = {
  name: 'Person',
  properties: {
    name:     'string',
    birthday: 'date',
    cars:     {type: 'list', objectType: 'Car'},
    picture:  {type: 'data', optional: true}, // optional property
  }
};

// Initialize a Realm with Car and Person models
let realm = new Realm({schema: [CarSchema, PersonSchema]});

If you’d prefer your objects inherit from an existing class, you just need to define the schema on the object constructor and pass in the constructor when creating a realm:

class Person {
  get ageSeconds() {
    return Math.floor((Date.now() - this.birthday.getTime()));
  }
  get age() {
    return ageSeconds() / 31557600000;
  }
}

Person.schema = PersonSchema;

// Note here we are passing in the `Person` constructor
let realm = new Realm({schema: [CarSchema, Person]});

Once you have defined your object models you can create and fetch objects from the realm:

realm.write(() => {
  let car = realm.create('Car', {
    make: 'Honda',
    model: 'Civic',
    miles: 750,
  });

  // you can access and set all properties defined in your model
  console.log('Car type is ' + car.make + ' ' + car.model);
  car.miles = 1500;
});

Basic Property Types

Realm supports the following basic types: bool, int, float, double, string, data, and date.

  • bool properties map to JavaScript Boolean objects
  • int, float, and double properties map to JavaScript Number objects. Internally ‘int’ and ‘double’ are stored as 64 bits while float is stored with 32 bits.
  • string properties map to String
  • data properties map to ArrayBuffer
  • date properties map to Date

When specifying basic properties as a shorthand you may specify only the type rather than having to specify a dictionary with a single entry:

const CarSchema = {
  name: 'Car',
  properties: {
    // The following property types are equivalent
    make:   {type: 'string'},
    model: 'string',
  }
}

Object Properties

For object types you specify the name property of the object schema you are referencing:

const PersonSchema = {
  name: 'Person',
  properties: {
    // All of the following property definitions are equivalent
    car: {type: 'Car'},
    van: 'Car',
  }
};

When using object properties you need to make sure all referenced types are present in the schema used to open the Realm:

// CarSchema is needed since PersonSchema contains properties of type 'Car'
let realm = new Realm({schema: [CarSchema, PersonSchema]});

When accessing object properties, you can access nested properties using normal property syntax:

realm.write(() => {
  var nameString = person.car.name;
  person.car.miles = 1100;

  // create a new Car by setting the property to valid JSON
  person.van = {make: 'Ford', model: 'Transit'};

  // set both properties to the same car instance
  person.car = person.van;
});

List Properties

For list properties you must specify the property type as list as well as the objectType:

const PersonSchema = {
  name: 'Person',
  properties: {
    cars: {type: 'list', objectType: 'Car'},
  }
}

When accessing list properties a List object is returned. List has methods very similar to a regular JavaScript array. The big difference is that any changes made to a List are automatically persisted to the underlying Realm. Additionally, Lists belong to the underlying object they were acquired from - you can only get List instances by accessing a property from an owning object and they cannot be manually created.

let carList = person.cars;

// Add new cars to the list
realm.write(() => {
  carList.push({make: 'Honda', model: 'Accord', miles: 100});
  carList.push({make: 'Toyota', model: 'Prius', miles: 200});
});

let secondCar = carList[1].model;  // access using an array index

Optional Properties

Properties can be declared as optional or non-optional by specifying the optional designator in your property definition:

const PersonSchema = {
  name: 'Person',
  properties: {
    name:     {type: 'string'},               // required property
    birthday: {type: 'date', optional: true}, // optional property

    // object properties are always optional
    car:      {type: 'Car'},
  }
};

let realm = new Realm({schema: [PersonSchema, CarSchema]});

realm.write(() => {
  // optional properties can be set to null or undefined at creation
  let charlie = realm.create('Person', {
    name: 'Charlie',
    birthday: new Date(1995, 11, 25),
    car: null,
  });

  // optional properties can be set to `null`, `undefined`,
  // or to a new non-null value
  charlie.birthday = undefined;
  charlie.car = {make: 'Honda', model: 'Accord', miles: 10000};
});

As seen above object properties are always optional and do not need an optional designation. List properties cannot be declared as optional or set to null. You can set or initialize a list with an empty array to clear it.

Default Property Values

Default property values can be specified by setting the default designator in the property definition. To use a default value, leave the property unspecified during object creation.

const CarSchema = {
  name: 'Car',
  properties: {
    make:  {type: 'string'},
    model: {type: 'string'},
    drive: {type: 'string', default: 'fwd'},
    miles: {type: 'int',    default: 0}
  }
};

realm.write(() => {
  // Since `miles` is left out it defaults to `0`, and since
  // `drive` is specified, it overrides the default value
  realm.create('Car', {make: 'Honda', model: 'Accord', drive: 'awd'});
});

Primary Keys

You can specify the primaryKey property in an object model for string and int properties. Declaring a primary key allows objects to be looked up and updated efficiently and enforces uniqueness for each value. Once an object with a primary key has been added to a Realm the primary key cannot be changed.

const BookSchema = {
  name: 'Book',
  primaryKey: 'id',
  properties: {
    id:    'int',    // primary key
    title: 'string',
    price: 'float'
  }
};

Writes

All changes to an object (addition, modification and deletion) must be done within a write transaction.

Write transactions incur non-negligible overhead - you should architect your code to minimize the number of write transactions.

Creating Objects

As shown above, objects are created using the create method:

let realm = new Realm({schema: [CarSchema]);

realm.write(() => {
  realm.create('Car', {make: 'Honda', model: 'Accord', drive: 'awd'});
});

Nested Objects

If an object has object properties, values for those properties can be created recursively by specifying JSON values for each child property:

let realm = new Realm({schema: [PersonSchema, CarSchema]);

realm.write(() => {
  realm.create('Person', {
    name: 'Joe',
    // nested objects are created recursively
    car: {make: 'Honda', model: 'Accord', drive: 'awd'},
  });
});

Updating Objects

Typed Updates

You can update any object by setting its properties within a write transaction.

realm.write(() => {
  car.miles = 1100;
});

Creating and Updating Objects With Primary Keys

If your model class includes a primary key, you can have Realm intelligently update or add objects based off of their primary key values. This is done by passing true as the third argument to the create method:

realm.write(() => {
  // Create a book object
  realm.create('Book', {id: 1, title: 'Recipes', price: 35});

  // Update book with new price keyed off the id
  realm.create('Book', {id: 1, price: 55}, true);
});

In the example above, since an object already exists with the id value of 1 and we have passed in true for the third argument, the price property is updated rather than trying to create a new object. Since the title property is omitted the object retains the original value for this property. Note that when creating or updating objects with primary key properties the primary key must be specified.

Deleting Objects

Objects can be deleted by calling the delete method within a write transaction.

realm.write(() => {
  // Create a book object
  let book = realm.create('Book', {id: 1, title: 'Recipes', price: 35});

  // Delete the book
  realm.delete(book);

  // Delete multiple books by passing in a `Results`, `List`,
  // or JavaScript `Array`
  let allBooks = realm.objects('Book');
  realm.delete(allBooks); // Deletes all books
});

Queries

Queries allow you to get objects of a single type from a Realm, with the option of filtering and sorting those results. All queries (including queries and property access) are lazy in Realm. Data is only read when objects and properties are accessed. This allows you to represent large sets of data in a performant way.

When performing queries you are returned a Results object. Results are simply a view or your data and are not mutable.

The most basic method for retrieving objects from a Realm is using the objects method on a Realm to get all objects of a given type:

let dogs = realm.objects('Dog'); // retrieves all Dogs from the Realm

Filtering

You can get a filtered Results by calling the filtered method with a query string.

For example, the following would change our earlier example to retrieve all dogs with the color tan and names beginning with ‘B’:

let dogs = realm.objects('Dog');
let tanDogs = dogs.filtered('color = "tan" AND name BEGINSWITH "B"');

Sorting

Results allows you to specify a sort criteria and order based on a single or multiple properties. For example, the following call sorts the returned cars from the example above numerically by miles:

let hondas = realm.objects('Car').filtered('make = "Honda"');

// Sort Hondas by mileage
let sortedHondas = hondas.sorted('miles');

Note that the order of Results is only guaranteed to stay consistent when the query is sorted. For performance reasons, insertion order is not guaranteed to be preserved.

Auto-Updating Results

Results instances are live, auto-updating views into the underlying data, which means results never have to be re-fetched. Modifying objects that affect the query will be reflected in the results immediately.

let hondas = realm.objects('Car').filtered('make = "Honda"');
// hondas.length == 0

realm.write(() => {
  realm.create('Car', {make: 'Honda', model: 'RSX'});
});
// hondas.length == 1

This applies to all Results instances, included those returned by the objects, filtered, and sorted methods.

This property of Results not only keeps Realm fast and efficient, it allows your code to be simpler and more reactive. For example, if your view relies on the results of a query, you can store the Results in a property and access it without having to make sure to refresh its data prior to each access.

You can subscribe to change events to know when Realm data is updated, indicating when your app’s UI should be refreshed for example, without having to re-fetch your Results.

Limiting Results

Most other database technologies provide the ability to ‘paginate’ results from queries (such as the ‘LIMIT’ keyword in SQLite). This is often done out of necessity to avoid reading too much from disk, or pulling too many results into memory at once.

Since queries in Realm are lazy, performing this sort of paginating behavior isn’t necessary at all, as Realm will only load objects from the results of the query once they are explicitly accessed.

If for UI-related or other implementation reasons you require a specific subset of objects from a query, it’s as simple as taking the Results object, and reading out only the objects you need.

let cars = realm.objects('Car');

// get first 5 Car objects
let firstCars = Array.prototype.slice.call(cars, 0, 5);

Realms

Multiple Realms

It’s sometimes useful to have multiple Realms persisted at different locations. For example, you may want to bundle some data with your application in a Realm file, in addition to your main Realm. You can do this by specifying the path argument when initializing your realm. All paths are relative to the writable documents directory for your application:

// Open a realm at another path
let realmAtAnotherPath = new Realm({
  path: 'anotherRealm.realm',
  schema: [CarSchema]
});

Default Realm Path

You may have noticed in all previous examples that the path argument has been omitted. In this case the default Realm path is used. You can access and change the default Realm path using the Realm.defaultPath global property.

Schema Version

The last option available when opening a Realm is the schemaVersion property. When omitted, the schemaVersion property defaults to 0. You are required to specify the schemaVersion when initializing an existing Realm with a schema that contains objects that differ from their previous specification. If the schema was updated and the schemaVersion was not, an exception will be thrown.

const PersonSchema = {
  name: 'Person',
  properties: {
    name: 'string'
  }
};

// schemaVersion defaults to 0
let realm = new Realm({schema: [PersonSchema]});

const UpdatedPersonSchema = {
  // The schema name is the same, so previous `Person` object
  // in the Realm will be updated
  name: 'Person',
  properties: {
    name: 'string',
    dog:  'Dog'     // new property
  }
};

// this will throw because the schema has changed
// and `schemaVersion` is not specified
let realm = new Realm({schema: [UpdatedPersonSchema]});

// this will succeed and update the Realm to the new schema
let realm = new Realm({schema: [UpdatedPersonSchema], schemaVersion: 1});

Migrations

Migrations are currently limited to updating the schema and schemaVersion when opening a Realm as outlined above. Data migrations are not yet supported but may be added in the future.

Change Events

Change events are sent out when write transactions are completed. To register for change events:

// Observe Realm Change Events
realm.addListener('change', () => {
  // Update UI
  ...
});

// Unregister all listeners
realm.removeAllListeners();

React Native ListView

If you’d like to use List or Results instances as data for a ListView, it is highly recommended that you use the ListView and ListView.DataSource provided by the realm/react-native module:

import { ListView } from 'realm/react-native';

The API is exactly the same as React.ListView, so you can refer to the ListView documentation for usage information.

Troubleshooting

Crash Reporting

We encourage you to use a crash reporter in your application. Many Realm operations could potentially fail at runtime (like any other disk IO), so collecting crash reports from your application will help identify areas where either you (or us) can improve error handling and fix crashing bugs.

Most commercial crash reporters have the option of collecting logs. We strongly encourage you to enable this feature. Realm logs metadata information (but no user data) when throwing exceptions and in irrecoverable situations, and these messages can help debug when things go wrong.

Reporting Realm Issues

If you’ve found an issue with Realm, please either file an issue on GitHub or email us at help@realm.io with as much information as possible for us to understand and reproduce your issue.

The following information is very useful to us:

  1. Goals.
  2. Expected results.
  3. Actual results.
  4. Steps to reproduce.
  5. Code sample that highlights the issue (full working projects that we can compile ourselves are ideal).
  6. Version of Realm.
  7. Crash logs & stack traces. See Crash Reporting above for details.