Modifiers for observable
By default, observable
recursively makes all the values of plain objects and arrays recursively observable.
Besides that, it automatically converts functions without arguments into reactive views or derived properties.
For all other types of values just a reference is stored.
In general, this should just do what you need, but if you want you can override the default behavior using modifiers.
Note that modifiers are 'sticky', they are interpreted as being annotations.
They do not only apply to the current value, but also to all values that are assigned in the future to the same attribute.
Note that the attributes class instances (all objects that have a prototype) will not be made observable automatically by observable
.
It is considered to be the responsibility of the class definition / constructor function to mark the necessary attributes of a class instance observable / computed.
computed
Introduces a computed property, see computed
action
Marks a function as action, see action
asMap
Creates a new Observable Map instead of an Observable Object. See asMap
asReference
The most common modifier is asReference
.
If this modifier is used, observable
will not attempt to make the value observable.
Use this for example if you want to store a reference to a function, instead of creating a view based on that function.
You can also use it to prevent that plain objects or arrays are made observable automatically.
var test = observable({
x : 3,
doubler: function() {
return this.x*2;
},
someFunc: asReference(function() {
return this.x;
})
});
console.log(test.doubler); // === 6
console.log(test.someFunc); // still a function
asStructure
Can be used on non-cyclic, plain JavaScript values.
Instead of comparing old values with new values based on whether the reference has changed, values are compared using deep equality before notifying any observers.
This is useful if you are working with 'struct' like objects like colors or coordinates and each time return fresh objects with possibly the same values.
asStructure
can be used on reactive functions, plain objects and arrays.
var ViewPort = mobxReact.observer(React.createClass({
displayName: 'ViewPort',
componentWillMount: function() {
mobx.extendObservable(this, {
screenSize: {
width: 0,
height: 0
},
minSize: {
width: 400,
height: 300
},
viewPortSize: mobx.asStructure(function() {
return {
width: Math.max(this.screenSize.width, this.minSize.width),
height: Math.max(this.screenSize.height, this.minSize.height)
}
}
});
window.onresize = function() {
mobx.transaction(function() {
this.screenSize.width = window.innerWidth;
this.screenSize.height = window.innerHeight;
});
}.bind(this);
},
render: function() {
return (
<div style={{
width: this.viewPortSize.width,
height: this.viewPortSize.height
}}>
test
</div>
);
}
}));
In the above example, the computed method viewPortSize
returns a fresh object on each re-computation.
So MobX considers it to have changed always. This means that each resize
event of the browser will trigger a re-render of the
ViewPort
component.
However, if the window size is smaller that the minSize
, the resize doesn't need to influence the rendering anymore, as the computed
will return the same dimensions after each run. asStructure
signals to MobX that observers of this computation should only be triggered
if the value returned by the computed has structurally changed (by default strict equality is used to determine whether observers need to be notified).
This means that a new object that is returned from viewPortSize
won't trigger a render
if its contents are (structurally) the same as the previous value.
To use the asStructure
modifier in combination with the @computed
decorator, use the following:
@computed({ asStructure: true }) get viewPortSize() {
return {
width: Math.max(this.screenSize.width, this.minSize.width),
height: Math.max(this.screenSize.height, this.minSize.height)
}
}
asFlat
Similar to asReference
, except that asFlat
does not prevent its value from becoming observable, but only the children of the value.
It can be used for example to create an observable array or object that should not automatically make its children observable.
var todos = observable(asFlat([{
title: "make coffee",
completed: false
}]));
isObservable(todos); // true
isObservable(todos[0]); // false
isObservable(todos[0], "title"); // false