-
-
Notifications
You must be signed in to change notification settings - Fork 310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Computed computes value without demand #912
Comments
@Robbendebiene Such derived state, which depends on core-state or other derived-state is called a Computed Observable. It is automatically kept in sync when its underlying observables change. var x = Observable(10);
var y = Observable(10);
var total = Computed((){
return x.value + y.value;
});
x.value = 100; // recomputes total
y.value = 100; // recomputes total again
print('total = ${total.value}'); // prints "total = 200" |
@amondnet Thanks for your reply. If you run: void main() {
var x = Observable(10);
var y = Observable(10);
var total = Computed((){
print("recompute");
return x.value + y.value;
});
x.value = 100;
y.value = 100;
print('total = ${total.value}');
} You get:
Because the Computed is only computed on "read" (last line with I can also demonstrate this with your example: void main() {
var x = Observable(0);
var total = Computed((){
print("recompute on ${x.value}");
return x.value;
});
reaction((p0) => total.value, (v) {
print("reaction: $v");
}, delay: 1000);
runInAction(() => x.value = 1);
runInAction(() => x.value = 2);
runInAction(() => x.value = 3);
runInAction(() => x.value = 4);
runInAction(() => x.value = 5);
runInAction(() => x.value = 6);
} Logs:
My question basically is why does it recompute for |
@Robbendebiene import 'package:fake_async/fake_async.dart';
import 'package:mobx/mobx.dart';
import 'package:test/test.dart';
void main() async {
test('gh-912', () {
fakeAsync((async) {
var x = Observable(0);
var total = Computed(() {
print("recompute on ${x.value}");
return x.value;
});
final disposer = reaction((p0) => total.value, (v) {
print("reaction: $v");
}, delay: 1000);
runInAction(() => x.value = 1);
async.elapse(Duration(milliseconds: 500));
runInAction(() => x.value = 2);
async.elapse(Duration(milliseconds: 500));
runInAction(() => x.value = 3);
async.elapse(Duration(milliseconds: 500));
runInAction(() => x.value = 4);
async.elapse(Duration(milliseconds: 500));
runInAction(() => x.value = 5);
async.elapse(Duration(milliseconds: 500));
runInAction(() => x.value = 6);
async.elapse(Duration(milliseconds: 500));
disposer();
});
});
}
|
Ah, right I forgot about this. This makes sense. So it works like this:
Thank you! So I thought I can prevent this (in my case) unintended recompute by simply using void main() async {
var x = Observable(0);
var total = Computed((){
print("recompute on ${x.value}");
return x.value;
});
autorun((_) {
print("reaction: ${total.value}");
}, delay: 1000);
runInAction(() => x.value = 1);
runInAction(() => x.value = 2);
runInAction(() => x.value = 3);
await Future.delayed(Duration(seconds: 2));
runInAction(() => x.value = 4);
runInAction(() => x.value = 5);
runInAction(() => x.value = 6);
}
I guess similar to the first case I feel like it must be possible to somehow circumvent this recomputation of 4. Any help is greatly appreciated. |
I'm trying to use
Computed
for JSON serialization and automatic storage updates. It works perfectly. However my concern was that it might cause performance problems. I feared that the JSON would be computed for every single property change. So I did some testing which can be seen below. Fortunately MobX holds its promise and the JSON is not recreated for every single property change when reacting to it with a delay (which I guess is similar to debounced event listening).I noticed though that it recreates the JSON object on the first modification, but I don't really understand why. Can someone please explain this to me?
My goal is to only compute the JSON on demand (when a reaction "demands" the value).
Thanks for creating this great package!
Classes
Console log
The first and the last "recompute" seems reasonable to me (the last one is desired in my case and the first one is probably some initialisation). What I don't get is the "recompute" after "add second".
The text was updated successfully, but these errors were encountered: