nullableStream<T> method

AsyncValue<T>? nullableStream<T>(
  1. Stream<T>? stream
)

Consumes a nullable Stream and watches the given stream.

If the given stream changes between build calls, then the current StreamSubscription will be disposed and recreated for the new stream. Thus, it is important that the stream instance only changes when needed. It is incorrect to create a stream in the same build as the stream, unless you use something like memo to limit changes. Or, if possible, it is even better to wrap the stream in an entirely new capsule (although this is not always possible).

This side effect also caches the data from the latest non-null stream, passing it into AsyncLoading.previousData when the stream switches and AsyncError.previousData when a new stream emits an exception. To remove this cached data from the returned AsyncValue, you may call AsyncValueConvenience.withoutPreviousData.

Implementation

AsyncValue<T>? nullableStream<T>(Stream<T>? stream) {
  final (getValue, setValue) = use.data<AsyncValue<T>>(
    AsyncLoading<T>(None<T>()),
  );

  use.effect(
    () {
      setValue(AsyncLoading(getValue().data));

      final subscription = stream?.listen(
        (data) => setValue(AsyncData(data)),
        onError: (Object error, StackTrace trace) =>
            setValue(AsyncError(error, trace, getValue().data)),
        cancelOnError: false,
      );
      return () => subscription?.cancel();
    },
    [stream],
  );

  return stream == null ? null : getValue();
}