Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MobX autorun behavior

I'm exploring MobX and went intrigued by a problem:

If I have this observable:

class ItemsStore {
    @observable items = [1,2,3];
}
const store = new ItemsStore;

and then change it like this:

setInterval(() => {
    store.items[0] = +new Date
}, 1000)

I noticed the following:

  • autorun(() => console.log(store.items)); never fires...
  • autorun(() => console.log(store.items[0])); fires every 1s and gives a new value
  • autorun(() => console.log(store.items.length)); fires every 1s although value is unchanged

What is the API logic behind this? I would expect that since store.items never fires, that unchanged properties would behave the same.

And how come MobX knows what code is inside my callback? is it analysing my callback I pass to autorun?

like image 772
Rikard Avatar asked Oct 29 '22 15:10

Rikard


1 Answers

console.log(store.items)

An autorun is fired when the observables that were dereferenced in the last autorun are changed. store.items does not dereference any observables. Try store.items.slice() or store.items.toJS() to get the desired effect.

console.log(store.items[0])

This fired because the observable that got dereferenced is changed.

console.log(store.items.length)

This is run because a MobX array is not a real array. The length property is defined as follows:

Object.defineProperty(ObservableArray.prototype, "length", {
    enumerable: false,
    configurable: true,
    get: function(): number {
        return this.$mobx.getArrayLength();
    },
    set: function(newLength: number) {
        this.$mobx.setArrayLength(newLength);
    }
});

getArrayLength reports that the MobX array has been observed:

getArrayLength(): number {
    this.atom.reportObserved();
    return this.values.length;
}
like image 93
Tholle Avatar answered Nov 15 '22 04:11

Tholle