Search code examples
javascriptreact-nativerealm

Can i accessing a property object that have Circular Reference from being Relationship method on my Nested Object Schema in Realm React Native


Hello Everyone

My React Native App use Realm for a database, but I found a little problem where I can't access a property that has been relationship with another Schema with Two-Many Relationship method, it's resulting a undefined but in the console.log() it's say an [[Circular]]

Here result from the console.log() when using REALM.objects('CUSTOMERS')[0] method and also my customer data structure

{
    "id": 1600502223352,
    "name": "Empink",
    "photo": "unknown",
    "dateCreated": 2020-09-19T07:58:29.086Z,
    "dateUpdated": 2020-09-19T07:58:29.086Z,
    "device": [[Circular]], // Relationship with "CUSTOMER_DEVICE" Schema
    "statusData": [[Circular]], // Relationship with "CUSTOMER_DATA_STATUS" Schema
    "downPayment": 50000,
    "servicePrice": 250000,
    "notes": "Phone Pin 3778"
}

I am try to access a device property directly like

let myDataObj = REALM.objects('CUSTOMERS');

console.log(myDataObj[0].device);

but it's resulting an Error

undefined is not an object (evaluating 'myDataObj[0].device')

This is my realmdb.js file and a Customer Data Schema looks like

In this file, a reason I export a Realm .open() method is that i want to call Realm from another file too

import Realm from 'realm';

const CUSTOMER_DEVICE = {
  name: 'CUSTOMER_DEVICE',
  primaryKey: 'id',
  properties: {
    id: 'int',
    brand: 'string',
    name: 'string',
    color: 'string',
    damage: 'string'
  }
};

const CUSTOMER_DATA_STATUS = {
  name: 'CUSTOMER_DATA_STATUS',
  primaryKey: 'id',
  properties: {
    id: 'int',
    type: 'string',
    date: 'date'
  }
};

const CUSTOMERS = {
  name: 'CUSTOMERS',
  primaryKey: 'id',
  properties: {
    id: 'int',
    dateCreated: 'date',
    dateUpdated: 'date',
    name: 'string',
    photo: 'string',
    device: 'CUSTOMER_DEVICE[]',
    statusData: 'CUSTOMER_DATA_STATUS[]',
    downPayment: 'float',
    servicePrice: 'float',
    notes: 'string'
  }
};

export default Realm.open({
  path: 'myApp.realm',
  schema: [CUSTOMER_DEVICE, CUSTOMER_DATA_STATUS, CUSTOMERS]
});

There's no error when I am try to add another data with Realm .write() and .create() method, it's just normally fine

And bay the way it's a just a little problem, I can use some method like call all schema > and Object.assign() all the data into one new variable but I don't really like it about this method because a performance reason

And if the Realm can't do that, there's no idea and i will use that method, OR maybe you guys know how to access a property that has been relationship with another Schema in Realm Javascript


Solution

  • Yes, you can!

    Since I searching and try understanding about my problem, try this, and try that, I just found some issue it's called JSON.stringify() cannot serialize cyclic structures also This Issue solve my problem too. see all Issue in Repo Realm Javascript

    First

    Realm Javascript has some method called JsonSerializationReplacer that solves circular structures when serializing Realm entities, it's mean a Circular Reference can be converted to a plain object

    How to usage

    import Realm from 'realm'
    
    // Imagine you're trying to retrieve a person data from Person Schema
    const SomeJsonString =
        JSON.stringify(Realm.objects('Person'), Realm.JsonSerializationReplacer);
    

    Example result WITHOUT JsonSerializationReplacer

    {
        "id": 1600502223352,
        "name": "Empink",
        "photo": "unknown",
        "dateCreated": 2020-09-19T07:58:29.086Z,
        "dateUpdated": 2020-09-19T07:58:29.086Z,
        "device": [Circular],
        "statusData": [Circular],
        "downPayment": 50000,
        "servicePrice": 250000,
        "notes": "Phone Pin 3778"
    }
    

    Example result WITH JsonSerializationReplacer

    {
        "id": 1600502223352,
        "name": "Empink",
        "photo": "unknown",
        "dateCreated": 2020-09-19T07:58:29.086Z,
        "dateUpdated": 2020-09-19T07:58:29.086Z,
        "device": {
            "name": "iPhone 5"
        },
        "statusData": {
            "type": "onprocess"
        },
        "downPayment": 50000,
        "servicePrice": 250000,
        "notes": "Phone Pin 3778"
    }
    

    Second

    DO NOT USE primaryKey property in Child Schema just use once in Parrent Schema it will be resulting an ERROR if you using JsonSerializationReplacer Method

    Simple example Bad Schema

    import Realm from 'realm';
    
    const CHILD_SCHEMA_1 = {
        name: "CHILD_1",
        primaryKey: "user_id",
        properties: {
            user_id: "string",
            user_name: "Mia"
        }
    };
    
    const CHILD_SCHEMA_2 = {
        name: "CHILD_2",
        primaryKey: "user_id",
        properties: {
            user_id: "string",
            user_hobby: "Coding Stuff"
        }
    };
    
    const PARRENT_SCHEMA = {
        name: "THE_PARRENT",
        primaryKey: "user_id",
        properties: {
            user_id: "string",
            user_details_1: "CHILD_1"
            user_details_2: "CHILD_2"
        }
    };
    
    Realm.open({
        schema: [CHILD_SCHEMA_1, CHILD_SCHEMA_2, PARRENT_SCHEMA]
    }).then(function(realm) {
        // do some realm stuff
    }).catch(function(RealmError){
        console.error(RealmError)
    });
    

    And that's it

    I don't know why Realm didn't add JsonSerializationReplacer, and the other things method to the Docs but in the end, it solve my problem :)