Decorators for creating model relationships with mobx
modeled-mobx is a lightweight layer on top of mobx 6 to easily serialize and hydrate javascript classes from JSON
Introduction
modeled-mobx replaces mobx's makeObservable
with a modelize
function. modelize
adds a "field" and "model" property to
configure the model's properties as observables that get and set their values when serialize
and hydrate
respectively are called.
It also includes a field
and model
decorator that can optionally be used instead of specifiying each property on the
options passed to modelize
Example
import { modelize, field, model, hydrate, serialize} from 'modeled-mobx'
import { observable, computed } from 'mobx'
class Item {
name: string = ''
material: string = ''
constructor() {
modelize(this, {
name: field,
material: observable,
})
}
}
export class Box {
@field width = 0;
@field height = 0;
@field depth = 0;
@observable serial: number = 0;
@computed get volume() {
return this.width * this.height * this.depth;
}
@model(Item) items: Item[] = [];
@model(Item) defaultItem?: Item = undefined;
constructor() {
modelize(this)
}
}
const box = hydrate(Box, {
width: 10, height: 10, depth: 10, serial: 1234,
items: [{ name: 'Box #1' }, { name: 'Box #2' }],
defaultItem: { name: 'Fruit' },
})
console.log(box.items[1].name, box.volume)
console.log(serialize(box))
Edge cases
properties must be assigned a value
When using Javascript, if a property is not initialized, Mobx will raise an exception: Cannot apply 'observable' to '<property name>': Field not found
for instance:
class Item {
name
constructor() {
modelize(this, {
name: field,
})
}
}
Will trigger the exception, but this usage is fine:
class Item {
name = ''
constructor() {
modelize(this, {
name: field,
})
}
}
This seems to be a limitation of ES6. If a field is present but not given a value, it will be "undefined", and MobX thinks that it's not present.