when<R> method

R when<R>({
  1. bool skipLoading = false,
  2. required R data(
    1. T data
    ),
  3. required R error(
    1. Object error,
    2. StackTrace stackTrace
    ),
  4. required R loading(),
  5. R none()?,
})

Allows you to define custom behavior for different states of an AsyncSnapshot by providing callbacks for data, error, loading, and none.

  • data Callbacks when snapshot has T data.
  • error Callbacks when snapshot hasError.
  • loading Callbacks when snapshot isLoading and hasNone.
  • none Optionally callbacks when snapshot not isLoading and hasNone.

Example:

snapshot.when(
  data: (data) => Text('Data: $data'),
  error: (error, stack) => Text('Error: $error'),
  loading: () => CircularProgressIndicator(),
  none: () => Text('No error or data'),
);

Use none for uncommon scenarios where data, error, and loading are not applicable. For instance, to display a widget when there's no data, no error, and no ongoing loading, or when a Stream is cancelled without emitting any data or error (e.g Stream.empty).

If none is not provided:

If skipLoading is true, loading won't be called when AsyncSnapshot hasData or hasError. Instead, data or error will be called.

It's recommended to use isReloading in conjunction with skipLoading. So all states are handled by ui.

Example:

Stack(
  alignment: Alignment.center,
  children: [
    snapshot.when(
      skipLoading: true,
      data: (data) => Text('Data: $data'),
      error: (error, stack) => Text('Error: $error'),
      loading: () => CircularProgressIndicator(),
      none: () => Text('No error or data'),
    );
    if(snapshot.isReloading)
    Align(
      alignment: Alignment.topCenter,
      child: LinearProgressIndicator(),
    ),
  ],
)

Implementation

R when<R>({
  bool skipLoading = false,
  required R Function(T data) data,
  required R Function(Object error, StackTrace stackTrace) error,
  required R Function() loading,
  R Function()? none,
}) {
  if (isLoading && !skipLoading) return loading();
  if (hasData) return data(this.data as T);
  if (hasError) return error(this.error!, stackTrace!);

  return switch (connectionState) {
    ConnectionState.none => none != null ? none() : loading(),
    ConnectionState.waiting => loading(),
    ConnectionState.active => loading(),
    ConnectionState.done when this.data is T => data(this.data as T),
    _ => none != null ? none() : data(requireData),
  };
}