Realm-js: [5.0.3] Can not easly copy a Realm object into an Object.

Created on 11 Apr 2020  路  6Comments  路  Source: realm/realm-js

Goals

I am trying to get some objects from a database and enriched them with other properties. To do so, I copy each realm object in a new one using :

copiedObj = {...originalObj, otherProperty: "someValue"}

Eventually the goal is to do a shallow copy of a realm object into a normal Object whithout having to iterate to each property of the original realm object.

Note: after some further testing, it works when Chrome Debugger is enabled, but doesn't if not.
Note 2: related to #2763 I guess.

Expected Results

Have a list of "enriched objects" with the new properties and the properties defined in realm schema.

Actual Results

I only get the new properties (if I don't explicitly copy the one from the schema one by one).

Steps to Reproduce

See below

Code Sample

class Users {
    static get () { return realm.objects(Users.schema.name) }
    static schema = {
        name: 'Users',
        primaryKey: 'id ',
        properties: {
            id: {type: 'string'},
            name: {type: 'string'}
        }
    }
}
const doStuff = () => {
    let users = Users.get();
    let usersCopied= [];

    console.log('--- Won t work ---')
    for (let i in users) {
        usersCopied.push({...users[i]});
    }
    usersCopied.forEach((item) => {
        console.log(item.name);
    })

    console.log('--- Will work ---')
    usersCopied= [];
    for (let i in users) {
        usersCopied.push({name : users[i].name,  id : users[i].id });
    }
    console.log('-----')
    usersCopied.forEach((item) => {
        console.log(item.name);
    })
}

Outputs

--- Won t work ---
undefined
undefined
undefined
--- Will work ---
Alice
Jean
Bernard

Version of Realm and Tooling

  • Realm JS SDK Version: 5.0.3
  • React Native: 0.62.2
  • Node : 12.16.1 (also tested with 10.20.1)
  • Client OS & Version: ANDROID
  • Which debugger for React Native: None
O-Community

Most helpful comment

@Frans-L
It's any code that can get the values by invoking the get property accessors on the prototype.
For example

let clone = {};
for (const key in obj) {
    clone[key] = obj[key];
}

there are also methods obj.key() and obj.entries() available on every Realm Object.

All 6 comments

You can have the additional properties on the User object and let Realm handle the schema properties.
What Realm does is it defines property accessors for every schema property on the prototype of any Realm Object instance. The additional properties on the class will be handled by the JS VM.

class Users {
     get myCustomProperty() { <------------
      return this.myProp();
    }

    static get () { return realm.objects(Users.schema.name) }
    static schema = {
        name: 'Users',
        primaryKey: 'id ',
        properties: {
            id: {type: 'string'},
            name: {type: 'string'}
        }
    }
}

Thanks for you quick answer @blagoev.

Beside, adding properties, to Realm Object instance, if i'm getting it straight, on V5 of Realm JS, there will be no way to "convert" a Realm Object instance into a classical object using :
classicalObj = {... realObjInstance}
It used to work on previous versions on Realm but from what I understand a lot of changes where done behind the scene on V5. Could you just confirm if there is a plan (or not, which is perfectly understandeble too) to make this work again ? Just to know if I should do some refactoring to implement V5 or if I should wait a little more.

Thanks !

Yes indeed, what previously were "magic" properties on the instance (which were going to the database behind the scene) are now regular property accessors on the prototype of the Realm Object instances. There are not plans to move back to instance properties.

cheers

What is now the recommend way to convert a Realm Object instance to a pure JS object?

The problem with the Realm Objects is that they are mutable, and sometimes immutable objects are needed with React, so converting them to a immutable JS objects has been a handy feature.

Maybe adding 1-2 lines about what is recommend way to make an immutable copy to docs would be great! :)

@Frans-L
It's any code that can get the values by invoking the get property accessors on the prototype.
For example

let clone = {};
for (const key in obj) {
    clone[key] = obj[key];
}

there are also methods obj.key() and obj.entries() available on every Realm Object.

You can do a workaround, Encode in JSON and then Decode back, and you have true deep copy. Though not an ideal solution.

Have look at this swift code if it helps, check out second step: here

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fever324 picture fever324  路  4Comments

MihaelIsaev picture MihaelIsaev  路  3Comments

blagoev picture blagoev  路  3Comments

timanglade picture timanglade  路  3Comments

kontinuity picture kontinuity  路  3Comments