derivedFuture<T> static method

DerivedFutureBeacon<T> derivedFuture<T>(
  1. Future<T> compute(), {
  2. bool manualStart = false,
})

Creates a DerivedBeacon whose value is derived from an asynchronous computation. This beacon will recompute its value every time one of its dependencies change. The result is wrapped in an AsyncValue, which can be in one of three states: loading, data, or error.

If manualStart is true, the future will not execute until start() is called.

Example:

  final counter = Beacon.writable(0);

  // The future will be recomputed whenever the counter changes
  final derivedFutureCounter = Beacon.derivedFuture(() async {
    final count = counter.value;
    await Future.delayed(Duration(seconds: count));
    return '$count second has passed.';
  });

  class FutureCounter extends StatelessWidget {
  const FutureCounter({super.key});

  @override
  Widget build(BuildContext context) {
    return switch (derivedFutureCounter.watch(context)) {
      AsyncData<String>(value: final v) => Text(v),
      AsyncError(error: final e) => Text('$e'),
      AsyncLoading() => const CircularProgressIndicator(),
    };
  }
}

Implementation

static DerivedFutureBeacon<T> derivedFuture<T>(
  Future<T> Function() compute, {
  bool manualStart = false,
}) {
  final beacon = DerivedFutureBeacon<T>(manualStart: manualStart);

  final unsub = effect(() async {
    // beacon is manually triggered if in idle state
    if (beacon.status.value == DerivedFutureStatus.idle) return;

    // start loading and get the execution ID
    final exeID = beacon.startLoading();

    try {
      final result = await compute();
      beacon.setAsyncValue(exeID, AsyncData(result));
    } catch (e, s) {
      beacon.setAsyncValue(exeID, AsyncError(e, s));
    }
  });

  beacon.$setInternalEffectUnsubscriber(unsub);

  return beacon;
}