setState<R> method Null safety

Future<T> setState<R>(
  1. FutureOr<R> fn(
    1. T s
    ),
  2. {@Deprecated('User sideEffects.onData instead') void onData(
    1. T data
    )?,
  3. @Deprecated('User sideEffects.onError instead') void onError(
    1. dynamic error
    )?,
  4. @Deprecated('User sideEffects instead') On<void>? onSetState,
  5. @Deprecated('User sideEffects instead') void onRebuildState(
      )?,
    1. SideEffects<T>? sideEffects,
    2. SnapState<T>? stateInterceptor(
      1. SnapState<T> currentSnap,
      2. SnapState<T> nextSnap
      )?,
    3. int debounceDelay = 0,
    4. int throttleDelay = 0,
    5. bool shouldAwait = false,
    6. bool skipWaiting = false,
    7. BuildContext? context,
    8. bool shouldOverrideDefaultSideEffects(
      1. SnapState<T> snap
      )?}
    )
    inherited

    Mutate the state of the model and notify observers.

    • Required parameters:
    • The mutation function. It takes the current state fo the model. The function can have any type of return including Future and Stream.
    • Optional parameters:
    • sideEffects: Used to handle side effects resulting from calling this method. It takes SideEffects object. Notice that SideEffects.initState and SideEffects.dispose are never called here.
    • shouldOverrideDefaultSideEffects: used to decide when to override the default side effects defined in RM.inject and other equivalent methods.
    • debounceDelay: time in milliseconds to debounce the execution of setState.
    • throttleDelay: time in milliseconds to throttle the execution of setState.
    • skipWaiting: Wether to skip waiting state.
    • shouldAwait: Wether to await of any existing async call.
    • silent: Whether to silent the error of no observers is found.
    • context: The BuildContext to be used for side effects (Navigation, SnackBar). If not defined a default BuildContext obtained from the last added StateBuilder will be used.

    Implementation

    Future<T> setState<R>(
      FutureOr<R> Function(T s) fn, {
      @Deprecated('User sideEffects.onData instead')
          void Function(T data)? onData,
      @Deprecated('User sideEffects.onError instead')
          void Function(dynamic error)? onError,
      @Deprecated('User sideEffects instead') On<void>? onSetState,
      @Deprecated('User sideEffects instead') void Function()? onRebuildState,
      SideEffects<T>? sideEffects,
      SnapState<T>? Function(SnapState<T> currentSnap, SnapState<T> nextSnap)?
          stateInterceptor,
      int debounceDelay = 0,
      int throttleDelay = 0,
      bool shouldAwait = false,
      bool skipWaiting = false,
      BuildContext? context,
      bool Function(SnapState<T> snap)? shouldOverrideDefaultSideEffects,
    }) async {
      final debugMessage = this.debugMessage;
      this.debugMessage = null;
      final call = _reactiveModelState.setStateFn(
        (s) {
          // assert(s != null);
    
          return fn(s as T);
        },
        middleState: (s) {
          final snap = _middleSnap(
            s,
            onError: onError,
            onData: onData,
            shouldOverrideGlobalSideEffects:
                shouldOverrideDefaultSideEffects?.call(s) ?? false,
            onSetState: sideEffects?.onSetState != null
                ? On(() {
                    sideEffects!.onSetState!(s);
                  })
                : onSetState,
            middleSnapState: stateInterceptor != null
                ? (middle) =>
                    stateInterceptor(middle.currentSnap, middle.nextSnap)
                : null,
          );
    
          if (snap != null && snap.hasData) {
            if (sideEffects?.onAfterBuild != null) {
              sideEffects!.onAfterBuild!();
            } else if (onRebuildState != null) {
              WidgetsBinding.instance?.addPostFrameCallback(
                (_) => onRebuildState(),
              );
            }
          }
          return snap;
        },
        onDone: (s) {
          return s;
        },
        skipWaiting: skipWaiting,
        debugMessage: debugMessage,
      );
      if (debounceDelay > 0) {
        subscription?.cancel();
        _debounceTimer?.cancel();
        _debounceTimer = Timer(
          Duration(milliseconds: debounceDelay),
          () {
            call();
            _debounceTimer = null;
          },
        );
        return Future.value(_state);
      } else if (throttleDelay > 0) {
        if (_debounceTimer != null) {
          return Future.value(_state);
        }
        _debounceTimer = Timer(
          Duration(milliseconds: throttleDelay),
          () {
            _debounceTimer = null;
          },
        );
      }
    
      if (shouldAwait && isWaiting) {
        return stateAsync.then(
          (_) async {
            final snap = await call();
            return snap.data as T;
          },
        );
      }
    
      final snap = await call();
      return snap.state;
    }