mobx.dart icon indicating copy to clipboard operation
mobx.dart copied to clipboard

Proper way of turning an action into separate methods?

Open DanMossa opened this issue 3 years ago • 3 comments

Hey! Just want to first say that I'm really grateful for this package the work that went into it.

In the example shown below

import 'package:mobx/mobx.dart';

part 'counter.g.dart';

class Counter = CounterBase with _$Counter;

abstract class CounterBase with Store {
  @observable
  int value = 0;

  @action
  void setValue(int value) {
    print('Do stuff');
    __setValue(value);
  }

  @action
  void __setValue(int value) {
    this.value = value;
  }
}

Should the the @action annotation be above setValue, __setValue, or both? Meaning, does the @action only go above the method actually changing the observable? Or the one being called from the flutter ui?

Thanks!

DanMossa avatar Jun 08 '22 16:06 DanMossa

@DanMossa


import 'package:mobx/mobx.dart';

part 'counter.g.dart';

class Counter = CounterBase with _$Counter;

abstract class CounterBase with Store {
  @observable
  int value = 0;

  @action
  void setValue(int value) {
    print('Do stuff');
    this.value = value;
  }

}

https://mobx.netlify.app/api/action/

amondnet avatar Jun 15 '22 07:06 amondnet

Actions are functions that encapsulate the mutations on observables. They are used to give a semantic name to the operation, such as incrementCounter() instead of simply doing counter++. These semantic names are how you would identify the various operations happening in the domain, as exposed on the UI.

Additionally, actions also provide few other guarantees:

  • Changes to the observables are only notified at the end of the action. This ensures all mutations happen as an atomic unit. This also eliminates noisy notifications, especially if you are changing a lot of observables (say, in a loop).
  • Actions can call other actions. For such nested actions, the change-notifications will be sent when the top-most action completes.
  • All the linked reactions (ones that depend on the observables mutated inside the action) are run only at the end of the action. This also ensures there are no pre-mature reactions occurring in the system.
import 'package:mobx/mobx.dart';

part 'counter.g.dart';

class Counter = CounterBase with _$Counter;

abstract class CounterBase with Store {
  @observable
  int value = 0;

  @action
  void setValue(int value) {
    print('Do stuff');
    this.value = 1;
    this.value = 2;
    this.value = value;
    // notify [value]
  }

  void setValueWithoutAction(int value) {
    print('Do stuff');
    this.value = 1;
    this.value = 2;
    this.value = value;
    // notify [1, 2, value]
  }
}


void main() {
  final counter = Counter();
  autorun((_) => print(counter.value));

  print('set value');

  counter.value = 1;
  counter.value = 2;
  counter.value = 3;

  Future.delayed(Duration(milliseconds: 1000));


  print('setValue with action');
  counter.setValue(3);
  Future.delayed(Duration(milliseconds: 1000));

  print('setValue without action');
  counter.setValueWithoutAction(3);

  Future.delayed(Duration(milliseconds: 1000));

}
0
set value
1
2
3
setValue with action
Do stuff
3
setValue without action
Do stuff
1
2
3

amondnet avatar Jun 15 '22 08:06 amondnet

@amondnet

Hey! It seems like you may have misread what I wrote.

I was more so asking if the action needs to be on the function that is actually changing the variable or both.

DanMossa avatar Jun 15 '22 15:06 DanMossa