Realm Data Storage in React Native and Node.js
Tags: node, react, javascript, realm
Published: 2019-11-18 00:11:15

&nbsp;&nbsp;I've been developing a React Native application recently that stores some highly confidential information and it really made me stop and think about storage solutions. I'm traditionally a React web developer and I hadn't really stopped to consider the differences between web and native application development.

### Differences 
&nbsp;&nbsp;When you create a traditional web application or site, your data persistence is kept to the back-end, and when you need more information, or need to save some, you send HTTP requests back and forth with the server who will handle that with a database connection. If you have something more short term you need to store, like a user or session id, you have a handful of options such as cookies, session storage, and HTML 5 LocalStorage. This is a fine solution that has functioned elegantly for years and something we are all overly familiar with. But when it comes to mobile app development things can be a little trickier. In mobile app development come a new set of hurdles that users on desktops aren't faced with. Spotty connections, limited data plans, and slower network speeds. These sort of hurdles can present a large barrier in terms of application performance. If you need to gather a feed of photos, there is still no way around making a network request, using data, and relying on an internet connection. But what if there is data or pages a client uses frequently and are an integral part of the app whether the client is at home on wifi or across the world and roaming? Now we need a quick, reliable and safe place to save this data with a little more longevity than cookies. 

###Built in storage with React Native
&nbsp;&nbsp;React native comes with a built in storage solution that works across all platforms called AsyncStorage. Just like HTML 5's implementation of LocalStorage, it stores strings of data in a key - value pair, however AsyncStorage (as the name implies) stores data Asynchronously. The problem with AsyncStorage is that data can only be of the type "String" so data must constantly be converted back and forth, it cannot be reliably encrypted, and it can only store key - value pairs, which gets very complex for large data sets and the data can have no polymorphic relationships. 

###Enter Realm
&nbsp;&nbsp;Realm is a storage system built for all platforms that uses an object oriented approach to databases, and can interface with Java, Swift, Objective-C, JavaScript, and .Net. Realm is also handy in the fact that it dynamically encrypts data depending on environment, using `AES-256 standard encryption` on an Android Device, the built in `CommonCrypto` library in iOS and the `Crypto` library included in Windows for native Windows applications. This means less code for you, and 200% more flawlessly running environments!

###How to use Realm
&nbsp;&nbsp;Getting started with Realm is easy. First create a new React Native project: 
```react-native init <project-name>```
Then install Realm:
```npm install --save realm```
and then link Realm to your native project:
```react-native link realm```
<br>
So now we have a project created, lets see how to implement a super simple React Native App that utilizes Realm (from the Realm <a href="https://realm.io/docs/javascript/latest/">docs</a>)

```javascript
import Realm from 'realm';


//Create a simple class component
class <project-name> extends Component {
  constructor(props) {
    super(props);
    //initialize a piece of state that we will also be persisting
    this.state = { realm: null };
  }

  componentWillMount() {
    //open the realm database connection
    Realm.open({
      //define the schema. 
      schema: [{name: 'Dog', properties: {name: 'string'}}]
    }).then(realm => {
      realm.write(() => {
        //here we create a new Realm "Dog" object as if it was a class
        realm.create('Dog', {name: 'Rex'});
      });
      //here we update state with the data from Realm
      this.setState({ realm });
    });
  }

  render() {
    const info = this.state.realm
      ? 'Number of dogs in this Realm: ' + this.state.realm.objects('Dog').length
      : 'Loading...';

    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          {info}
        </Text>
      </View>
    );
  }
}
```

and here is a more in depth look at interfacing with Realm storage:

```javascript
const Realm = require('realm');

// Define your models and their properties
const CarSchema = {
  name: 'Car',
  properties: {
    make:  'string',
    model: 'string',
    miles: {type: 'int', default: 0},
  }
};
const PersonSchema = {
  name: 'Person',
  properties: {
    name:     'string',
    birthday: 'date',
    cars:     'Car[]',
    picture:  'data?' // optional property
  }
};

Realm.open({schema: [CarSchema, PersonSchema]})
  .then(realm => {
    // Create Realm objects and write to local storage
    realm.write(() => {
      const 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
    const cars = realm.objects('Car').filtered('miles > 1000');

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

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

    // Query results are updated in realtime
    cars.length // => 2
  })
  .catch(error => {
    console.log(error);
  });
```
It is important to note that Realm is also an _Asynchronous_ storage solution, like the built in AsyncStorage in React Native.

###Relationships
&nbsp;&nbsp;Just like complex database storage solutions using a back-end server, Realm supports complex relationships such as to-one and to-many's. For a to-one relationship, simply set the `type` of an object's property to the name of the related object, for example from the above code: 
```javascript
const PersonSchema = {
  name: 'Person',
  properties: {
    name:     'string',
    birthday: 'date',
    car:     'Car',
    picture:  'data?' // optional property
  }
};
```
The car property of the Person object (`Person.car`) is set to 'Car', or a Car object, declaring the relationship, instead of "string" or "integer" type. For a to-many relationship, simply append a "[]" to the Object Property, defining it as a list. From the example above:
```javascript
const PersonSchema = {
  name: 'Person',
  properties: {
    name:     'string',
    birthday: 'date',
    cars:     'Car[]',
    picture:  'data?' // optional property
  }
};
```
`Person.cars` now return a list of Car objects, because _one_ Person has _many_ cars. 

###Conclusion
If you are in need of a fast and secure storage solution in a mobile application that handles large sets of data in a locally stored, easy to digest manner, look no further than Realm. The documentation <a href="https://realm.io/docs/javascript/latest/">here</a> is extremely helpful, and describes all of the complex actions Realm can handle, including direct queries, advanced relationships, migrations, and encryption.