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.4k stars 310 forks source link

Breaking change between mobx_codegen 2.0.4 and 2.0.6 ("late" and "context") #803

Closed jfahrenkrug closed 2 years ago

jfahrenkrug commented 2 years ago

We noticed that when we had a dependency on mobx_codegen 2.0.4, it produced errors when running on Windows. The errors looked like this:

type 'UnspecifiedInvalidResult' is not a subtype of type 'LibraryElementResult' in type cast

There seems to be an issue in the source_gen package: https://github.com/dart-lang/source_gen/issues/557 These issues only happened on Windows, not on macOS. However, when updating to mobx_codegen 2.0.6, the build_runner finishes successfully, BUT the generated code is invalid. It made every instance of Atom late and added a context parameter that would not compile. This would happen both on Windows and on macOS.

It would turn this:

final _$statusAtom = Atom(name: '_ConnectivityStoreBase.status');

into this:

late final _$statusAtom = Atom(name: '_ConnectivityStoreBase.status', context: context);

Our solution is to add source_gen as a direct dependency and to keep mobx_codegen at version 2.0.4:

dev_dependencies:
  build_runner: ^2.1.10
  mobx_codegen: 2.0.4
  source_gen: 1.2.2
  flutter_test:
    sdk: flutter

However, we don't want to get stuck on version 2.0.4 forever :) What is the reason for the "stray" late and contexts being added in 2.0.6? Is that a bug? Can it be turned off? Thanks!

amondnet commented 2 years ago

Use mobx ^2.0.7.

dependencies:
  mobx: ^2.0.7

https://github.com/mobxjs/mobx.dart/pull/770 https://github.com/mobxjs/mobx.dart/blob/9c4eb1dbd99228cbc11425b59472f6142b3816fd/mobx/lib/src/api/store.dart#L11

jfahrenkrug commented 2 years ago

@amondnet Thank you. I think I'm missing some context here (haha). What exactly changed and why is this necessary? Is there a place where I can read up on this? Thank you!!

amondnet commented 2 years ago

@jfahrenkrug

The MobX reactive system operates in a context where it is aware of the various observables and their linked reactions. Within this context, if an observable changes, any linked reaction would automatically execute. By default, there is a singleton, top-level context called the mainContext. All reactivity occurs within this context.

Creating custom context is an advanced feature and not needed for your normal usage.

However, MobX also allows you to create your own context and run reactions specifically within that. This is useful if you have independent reactive systems that don't need to share the same context. Imagine a library that uses MobX internally to run some reactivity. If that library is used in a Flutter app, which is also using MobX, there is no need for the library and the app to share the mainContext. This is a good use-case for creating a custom context.

770 allow custom ReactiveContext creation with codegen.

class CustomContextStore = _CustomContextStore with _$CustomContextStore;

final ReactiveContext customContext = ReactiveContext();

abstract class _CustomContextStore with Store {
  @observable
  late String name;

  @override
  ReactiveContext get context => customContext;
}