First off, MobX is freaking amazing! Am writing a big spreadsheet component with it... code is scaling well, easy to extend. Would be insane without MobX...
I'm chasing some re-render issues and find some odd behavior. Using mobx 2.7.0, testing with Karma inside Chrome 55.
Issue: A @computed expression is being re-evaluated, although the underlying data is unchanged.
class ObservablePerson {
@observable first;
@observable last;
fullNameComputations = 0;
constructor(first, last) {
this.first = first;
this.last = last;
}
@computed get fullName() {
this.fullNameComputations++;
console.log("Computing full name!");
return `${this.first} ${this.last}`;
}
@computed get summary() {
return this.fullName;
}
}
it("calcs fullname when needed", () => {
useStrict(false);
var hjs = new ObservablePerson("homer", "simpson");
//autorun(()=> {
// console.log(jw.fullName);
//});
//console.log(hjs.summary);
expect(hjs.fullName).to.equal("homer simpson");
expect(hjs.fullNameComputations).to.equal(1);
expect(hjs.fullName).to.equal("homer simpson");
expect(hjs.fullName).to.equal("homer simpson");
expect(hjs.fullName).to.equal("homer simpson");
expect(hjs.fullName).to.equal("homer simpson");
expect(hjs.fullName).to.equal("homer simpson");
expect(hjs.fullNameComputations).to.equal(1);
});
fullName is not memoized, and the test fails:
16:56:06 test.1 | LOG: 'Computing full name!'
16:56:06 test.1 | LOG: 'Computing full name!'
16:56:06 test.1 | LOG: 'Computing full name!'
16:56:06 test.1 | LOG: 'Computing full name!'
16:56:06 test.1 | LOG: 'Computing full name!'
16:56:06 test.1 | LOG: 'Computing full name!'
16:56:06 test.1 | Chrome 55.0.2883 (Mac OS X 10.10.4) ValidatedGridState computed expressions calcs fullname when needed FAILED
16:56:06 test.1 | AssertionError: expected 6 to equal 1
Interestingly, the behavior can be changed by uncommenting the 2 blocks. Autorun forces memoization and makes the test pass.
Uncommenting console.log(hjs.summary); results in 2 recalcs.
Is this expected?
It's expected. If it's not observed it will not be memoized.
Per: https://mobxjs.github.io/mobx/best/pitfalls.html
Computed values run more often then expected
If a computed property is not in use by some reaction (autorun,
observer etc),
computed expressions will be evaluated lazily; each time their value is
requested (so they just act as normal property). Computed values will only
track their dependencies if they are observed. This allows MobX to
automatically suspend computations that are not actively in use. See this
blog
https://medium.com/@mweststrate/becoming-fully-reactive-an-in-depth-explanation-of-mobservable-55995262a254
or issue #356 https://github.com/mobxjs/mobx/issues/356 for an
explanation. So if you fiddle arounds, computed properties might not seem
efficient. But when applied in a project that uses observer, autorun etc,
they become very efficient.
On Thu, Dec 22, 2016 at 4:08 PM, Jeff Winkler notifications@github.com
wrote:
I'm chasing some re-render issues and find some odd behavior. Using mobx
2.7.0, testing with Karma inside Chrome 55.Issue: A @computed https://github.com/computed expression is being
re-evaluated, although the underlying data is unchanged.class ObservablePerson {
@observable first;
@observable last;
fullNameComputations = 0;constructor(first, last) {
this.first = first;
this.last = last;
}@computed get fullName() {
this.fullNameComputations++;
console.log("Computing full name!");
return${this.first} ${this.last};
}@computed get summary() {
return this.fullName;
}
}it("calcs fullname when needed", () => {
useStrict(false);
var hjs = new ObservablePerson("homer", "simpson");
//autorun(()=> {
// console.log(jw.fullName);
//});//console.log(hjs.summary);
expect(hjs.fullName).to.equal("homer simpson");
expect(hjs.fullNameComputations).to.equal(1);expect(hjs.fullName).to.equal("homer simpson");
expect(hjs.fullName).to.equal("homer simpson");
expect(hjs.fullName).to.equal("homer simpson");
expect(hjs.fullName).to.equal("homer simpson");
expect(hjs.fullName).to.equal("homer simpson");expect(hjs.fullNameComputations).to.equal(1);
});fullName is not memoized, and the test fails:
16:56:06 test.1 | LOG: 'Computing full name!'
16:56:06 test.1 | LOG: 'Computing full name!'
16:56:06 test.1 | LOG: 'Computing full name!'
16:56:06 test.1 | LOG: 'Computing full name!'
16:56:06 test.1 | LOG: 'Computing full name!'
16:56:06 test.1 | LOG: 'Computing full name!'
16:56:06 test.1 | Chrome 55.0.2883 (Mac OS X 10.10.4) ValidatedGridState computed expressions calcs fullname when needed FAILED
16:56:06 test.1 | AssertionError: expected 6 to equal 1Interestingly, the behavior can be changed by uncommenting the 2
blocks. Autorun forces memoization and makes the test pass.Uncommenting console.log(hjs.summary); results in 2 recalcs.
Is this expected?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/mobxjs/mobx/issues/718, or mute the thread
https://github.com/notifications/unsubscribe-auth/AAIrcnT7uhNjNJc4VHrSigcvcJDlQeRTks5rKvTZgaJpZM4LUayr
.
--
-Matt Ruby-
[email protected]
👍 thanks for the thorough explanation Matt!
Most helpful comment
It's expected. If it's not observed it will not be memoized.
Per: https://mobxjs.github.io/mobx/best/pitfalls.html
Computed values run more often then expected
If a computed property is not in use by some reaction (autorun,
observer etc),
computed expressions will be evaluated lazily; each time their value is
requested (so they just act as normal property). Computed values will only
track their dependencies if they are observed. This allows MobX to
automatically suspend computations that are not actively in use. See this
blog
https://medium.com/@mweststrate/becoming-fully-reactive-an-in-depth-explanation-of-mobservable-55995262a254
or issue #356 https://github.com/mobxjs/mobx/issues/356 for an
explanation. So if you fiddle arounds, computed properties might not seem
efficient. But when applied in a project that uses observer, autorun etc,
they become very efficient.
On Thu, Dec 22, 2016 at 4:08 PM, Jeff Winkler notifications@github.com
wrote:
--
-Matt Ruby-
[email protected]