How to store [String] or [Int] in react-native realm - javascript

I've read online where in Android/iOS I should inherit from RealmObject and create my own RealmString to use as my objectType in a list.
What's the approach in react-native? I can't find any code samples on how to handle this issue.
Thanks

You can use the same strategy in react-native:
var intObject = {
name: 'intObject',
properties: { value: 'int' }
};
var intListObject = {
name: 'intListObject',
properties: {
'intList': { type: 'list', objectType: 'intObject' } }
};
var realm = new Realm({schema: [intObject, intListObject]});
var listObject = realm.create('intListObject', {
intList: [{value: 0}, {value: 2}, ...]
});
var value = listObject.intList[1].value; // 2
We plan to support arrays of primitive types without the extra abstraction but there isn't yet an eta for this feature.

Related

Turf JS does not create Object properly

I am using the helper function turf.point()
const feature = turfHelpers.point(coords, properties, { id: properties.id });
properties looks like this
properties = {
id: 1,
thisWorks: 'no problem'
foo: {
thisDoesntWork: 'this is a problem'
}
}
When I create feature with turfHelpers.point(), it messes with the object. The nested object is not an object anymore, but gets stringyfied...
So, features.properties is
{
id: 1,
thisWorks: 'no problem'
foo: "{
thisDoesntWork: 'this is a problem'
}"
}
Now, I cannot access. feature.properties.foo.thisDoesntWork anymore, because its a string...
Why is turf.js doing that?
Let's put the question in the runnable form.
const turfHelpers = turf.helpers;
const coords = [100, 14];
const properties = {
id: 1,
thisWorks: 'no problem',
foo: {
thisDoesntWork: 'this is a problem'
}
};
var feature1 = turfHelpers.point(coords, properties, {
id: properties.id
});
// Print out on console
console.log(feature1.properties); //look OK
console.log(feature1.properties.foo); //also OK
console.log(feature1.properties.foo.thisDoesntWork); //also OK
<script src="https://cdnjs.cloudflare.com/ajax/libs/Turf.js/5.1.5/turf.min.js"></script>
Then, hopefully, it is helpful for discussion that leads to a solution.

Using a Map instance to return an array of distinct objects by property name?

This implementation seems to be working fine (Stackblitz):
/**
* Returns all the elements that are distinct by the
* `property` value. Note that the implementation uses a `Map<string, E>` to
* index the entities by key. Therefore the more recent occurences
* matching a key instance will overwrite the previous ones.
*
* #param property The name of the property to check for distinct values by.
* #param entities The entities in the array.
*
* #example
* ```
* let todos:Todo = [{ id: 1, "Lets do it!" }, {id: 2, "All done!"}];
* let dtodos:Todo[] = distinct<Todo>(todos, 'id');
*/
export function distinct<E>(entities:E[], property:string):E[] {
let map:Map<string, E> = new Map();
entities.forEach((e:E)=>{
map.set(e[property], e);
});
return Array.from(map.values());
}
The only thing is that VSCode draws a red squiggly under the e[property] part and the error message is:
Element implicitly has an 'any' type because type '{}' has no index signature.ts(7017)
Is there a way to get rid of that?
Library Holding Implementation
I added the latest suggested implementation to this light weight state manager for objects and entities:
https://www.npmjs.com/package/#fireflysemantics/slice
npm i #fireflysemantics/slice
...
import {distinct} from '#fireflysemantics/slice/utilities';
Demo
https://stackblitz.com/edit/typescript-slice-distinct
The Error message is a bit misleading. His problem is, that it can not ensure that e[property] is of type string as you've defined the Map.
Make the key in the Map of type any as with so much flexibility you can not determine the type of the value either.
Additionally I'd type the property parameter as keyof E so TS ensures that I can only paste in valid property names for the type.
function distinct<E>(entities:E[], property:keyof E):E[] {
let map:Map<any, E> = new Map();
entities.forEach((e:E)=>{
map.set(e[property], e);
});
return Array.from(map.values());
}
Based on Thomas' answer, we can simplify both:
JavaScript code: constructing the Map at once;
TypeScript typing: adding the K extends keyof E, we can cast the tuples ([E[K], E]) used as Map constructor input parameter and remove the any type use.
Here the code:
function distinct<E, K extends keyof E>(entities: E[], property: K): E[] {
const entitiesByProperty = new Map(entities.map(e => [e[property], e] as [E[K], E]));
return Array.from(entitiesByProperty.values());
}
When calling distinct(), there's no need to specify the generic types since they can be inferred. Here's a working example:
enum Status { Pending = 0, Done = 1 }
interface Todo { id: number, label: string, status: Status, date?: Date }
const todos: Todo[] = [
{ id: 1, label: 'Task 1', status: Status.Pending },
{ id: 2, label: 'Task 2', status: Status.Pending },
{ id: 1, label: 'Task 1', status: Status.Done },
];
distinct(todos, 'id'); // [{ id: 1, ... status: 1 }, { id: 2, ... status: 0 }]

A more aesthetic way of copying an object literal?

This is client side. Webpack, Babel and Babel Imports.
My project has a folder called "models" which contains object literals as definitions of the expected JSON results from endpoints.
The objects only contain strings, ints, booleans and arrays/objects which contain those data types
eg:
{
name: "String"
age: 35,
active: true,
permissions: [
{ news: true }
]
}
When I want to use a model definition, in order to ensure I don't have issues with references, I must use:
let newObject1 = Object.assign({}, originalObj )
or
let newObject2 = JSON.parse( JSON.stringify( originalObj ))
I find this a bit ugly and it pollutes my code a bit.
I would love the ability to use the new keyword on object literals, but of course that's not a thing.
let clone = new targetObj
What's the most aesthetic way to handle the cloning of an object literal without creating a reference?
The JavaScript way of implementing such object "templates" are constructors:
function Original() {
this.name = "String";
this.age = 18;
this.active = true;
this.permissions = [
{ news: true }
];
}
var obj = new Original();
console.log(obj);
Or, in ES6 class syntax:
class Original {
constructor() {
this.name = "String";
this.age = 18;
this.active = true;
this.permissions = [
{ news: true }
];
}
}
let obj = new Original();
console.log(obj);
Be aware that Object.assign will only create a shallow copy, so it would not copy the permissions array, but provide a reference to the same array as in the original object.
const originalObject = {
name: "String",
age: 35,
active: true,
permissions: [
{ news: true }
]
};
let obj1 = Object.assign({}, originalObject);
let obj2 = Object.assign({}, originalObject);
// change a permission:
obj1.permissions[0].news = false;
// See what permissions are in obj2:
console.log(obj1.permissions);
const model = () => ({
name: 'string',
age: 20,
array: [ 1, 2, 3 ]
});
let newObject = model();
You won't have the pleasure of using new - see trincot's answer for that - but you don't have to worry about nested objects (assign) or feel gross (stringify + parse).

Create Primary Keys for Realm

Iam using Realm as Database backend for my react-native app.
Since Realm doesn't offer an auto creation for primary keys I would just increment the last known ID by 1.
How can I get the last known ID?
use this function logic
class MySchema extends Realm.Object {}
MySchema.schema = {
name: "MySchema",
primaryKey: 'id',
properties: {
id: "int",
myProperty: "string",
}
const myRealm = new Realm({
schema: MySchema,
})
getPrimaryKeyId(model) {
if (myRealm .objects(model).max("id")) {
return myRealm.objects(model).max("id") + 1;
}
return 1;
}
insertQuery(){
myRealm..write(() => {
realm.create("MySchema",{id:getPrimaryKeyId('MySchema'), myProperty:'propertyValue'});
})
}
}`

How to loop through specific keys in nested object?

I want to pull specific parts (definitely not all) from this object:
var metadata = {
cat: {
id: 'id',
name: 'kitty',
},
dog: {
id: 'id',
name: 'spot',
owner: {
name: 'ralph',
}
}
//tons of other stuff
};
I would like to do something like this:
var fields = ['cat.id', 'dog.name', 'dog.owner.name'];
fields.forEach( function(key) {
console.log(metadata[key]); //obv doesn't work
});
This is a simplified scenario where I'm trying to validate specific fields in metadata. Is there a straightforward way to do this?
Split the path to extract individual keys, then use a reducer to resolve the value, then map the results:
var path = function(obj, key) {
return key
.split('.')
.reduce(function(acc, k){return acc[k]}, obj)
}
var result = fields.map(path.bind(null, metadata))
//^ ['id', 'spot', 'ralph']
Now you can log them out if you want:
result.forEach(console.log.bind(console))

Categories