mobx: automatic tracking not working for nested objects?
I took the sample code from the documentation here and modified it a bit to use an object instead of an array for the todos field:
var todoStore = observable({
todos: { },
identity: function() { return this.todos; },
derived: function() {
let counter = 0; for(let key in this.todos) { ++counter; } return counter;
}
});
const print = function() {
console.log(
JSON.stringify(todoStore.todos),
JSON.stringify(todoStore.identity),
todoStore.derived
);
};
autorun(print);
// -> prints: { } { } 0
todoStore.todos.test = { title: "Take a walk", completed: false };
// -> should print: {"test":{"title":"Take a walk","completed":false}}
// {"test":{"title":"Take a walk","completed":false}} 1
todoStore.todos.test.completed = true;
// -> should print: {"test":{"title":"Take a walk","completed":true}}
// {"test":{"title":"Take a walk","completed":true}} 1
Now the whole automatic tracking doesn’t work anymore. The places marked with -> should print: ... do not print.
It I add another print(); call at the end of the sample code it prints this:
{"test":{"title":"Take a walk","completed":true}}
{"test":{"title":"Take a walk","completed":true}} 0
Note the wrong 0 at the end, since this should be 1!
Do I miss something here? Do I need to use mobservable for objects differently from how I would use it intuitively?
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 15 (7 by maintainers)
Commits related to this issue
- In contrast to the spec, observableArray.sort is actually an alias for observableArray.slice.sort, see #90 — committed to mobxjs/mobx by mweststrate 8 years ago
Objects themselves are not observable. Only their individual properties are. When mobservable makes an object observable, it will only do so for the properties that are on the object on that moment. (and
extendObservablecan be used to add after-the-fact properties).However, the set of keys, or the iterator, of an object is never observable (es5 simply hasn’t have a feature for that). So if you have the following:
So it boils down to this: anything with a fixed set of properties (plain data object, classes, etc. etc) can be made observable by using
observable/extendObservable.If you want to vary on the keys that exist on an object itself, you need
mapif the keys are non-numeric, and arrays if the keys are numeric. With map you can even subscribe to not yet existing keys.So in your case you need a map as you index your objects by some key. The objects inside that map are probably regular so
observable(obj)will suffice for them (observablewill be applied to any new values added to the map automatically by default)@Shadowman4205 try this one: