mobxjs / mobx.dart

MobX for the Dart language. Hassle-free, reactive state-management for your Dart and Flutter apps.
https://mobx.netlify.app
MIT License
2.39k stars 310 forks source link

late reactions not working #960

Closed subzero911 closed 9 months ago

subzero911 commented 9 months ago

If you initialize a late reaction right in the Store, it will never fire:

abstract class _FilteredTasksControllerBase with Store {

    @observable
    var tasks = ObservableList<Task>();

    late final r = reaction((_) => tasks.length, (len) async {
      log.wtf('reaction fired');
      await markAsSeen();
      await taskController.fetchTaskStats();
    });

}

But if you just declare it in the Store body and initialize in the constructor, it will do. Magic?

late final ReactionDisposer r;

_FilteredTasksControllerBase({
    required this.taskController,
    required this.currentStatus,
  }) {
    r = reaction((_) => tasks.length, (len) async {
      log.wtf('reaction fired');

      await markAsSeen();
      await taskController.fetchTaskStats();
    });
  }
fzyzcjy commented 9 months ago

IIRC it is because late final fields are lazy. If you never read them, then they will never be initialized.

subzero911 commented 9 months ago

That's crazy.

fzyzcjy commented 9 months ago

It's a dart feature IMHO

amondnet commented 9 months ago

https://dart.dev/language/variables#late-variables https://dart.dev/null-safety/understanding-null-safety#lazy-initialization

subzero911 commented 9 months ago

So if I initialize a late variable at declaration, it's considered to be a lazy initialization. But if I do it in the class constructor, it's considered as an assignment, and won't be lazy. If I understand correctly