react<Value> method

System<State, Event> react<Value>({
  1. required Value value(
    1. State state
    ),
  2. Equals<Value>? equals,
  3. bool skipInitialValue = true,
  4. required void effect(
    1. Value value,
    2. Dispatch<Event> dispatch
    ),
})

Add effect triggered by reacting to state's partial value change.

API Overview

system
  ...
  .react<int>(
    value: (state) => state.itemId, // map state to value, required
    equals: (value1, value2) {  // `equals` is used to determine if old value equals 
      return value1 == value2;  // to new value. If there are not equal, then effect
    },                          // is triggered. `equals` is nullable, defaults to 
                                // `==` as shown.
    skipInitialValue: true, // return true if initial value is skipped,
                            // which won't trigger effect.
                            // return false if initial value isn't skipped,
                            // which will trigger effect.
                            // `skipInitialValue` defaults to true if omitted.
    effect: (value, dispatch) { 
      // trigger effect here with new value, required
    },
  )
  ...

Usage Example

Below code showed how to send account changed event to analytics service, when user id changed.

system
  ...
  .react<String?>(
    value: (state) => state.userId,
    effect: (userId, dispatch) async {
      await analyticsService.onAccountChanged(userId);
    },
  )
  ...

Implementation

System<State, Event> react<Value>({
  required Value Function(State state) value,
  Equals<Value>? equals,
  bool skipInitialValue = true,
  required void Function(Value value, Dispatch<Event> dispatch) effect,
}) {
  final localEquals = equals ?? defaultEquals;
  return withContext<_ReactContext<Value>>(
    createContext: () => _ReactContext(),
    effect: (context, state, oldState, event, dispatch) {
      final localValue = value(state);
      final bool shouldUpdateOldValue;
      final bool shouldTriggerEffect;
      if (event == null) {
        shouldTriggerEffect = !skipInitialValue;
        shouldUpdateOldValue = true;
      } else {
        final oldValue = context.oldValue as Value;
        shouldTriggerEffect = !localEquals(oldValue, localValue);
        shouldUpdateOldValue = shouldTriggerEffect;
      }
      if (shouldUpdateOldValue) {
        context.oldValue = localValue;
      }
      if (shouldTriggerEffect) {
        effect(localValue, dispatch);
      }
    },
  );
}