LogoSignals.dart
Copy Markdown
rodydavis/signals.dart 999999

Type: computedFrom

API reference and details for computedFrom from signals.dart.

computedFrom#

Kind: function  |  Package: package:signals_core

Function: computedFrom#

FutureSignal<T> computedFrom(List<ReadonlySignal<A>> signals, Future<T> Function(List<A> args) fn, {AsyncSignalOptions<T>? options, @Deprecated('Use options: AsyncSignalOptions(initialValue: ...) instead') T? initialValue, @Deprecated('Use options: AsyncSignalOptions(lazy: ...) instead') bool? lazy, @Deprecated('Use options: AsyncSignalOptions(autoDispose: ...) instead') bool? autoDispose, @Deprecated('Use options: AsyncSignalOptions(name: ...) instead') String? debugLabel})

Create an asynchronous computed signal by explicitly declaring its dependencies.

computedFrom takes a list of signals and a callback function to compute the value of the signal every time one of the declared signals changes.

Unlike computedAsync, which tracks dependencies implicitly, computedFrom is immune to the Async Gap Gotcha because all tracking is declared upfront.

Why use computedFrom?#

When writing asynchronous code, Dart yields control at every await keyword. Implicit tracking (in computedAsync or computed) cannot track reads that happen after an asynchronous gap because the active reactive reader context is lost.

computedFrom solves this by:

  1. Subscribing to the list of input signals synchronously.
  2. Reading their latest values synchronously.
  3. Passing those resolved values into your callback as an ordered list of arguments.

Example: Fetching user details when an ID signal changes#

final userId = signal(123);

// The callback receives the current values of the declared signals
final userProfile = computedFrom([userId], (args) async {
  final currentId = args.first; // Type-safe list of dependencies
  return fetchUserProfileFromServer(currentId);
});

// userProfile is a FutureSignal<UserProfile> which can be pattern-matched
effect(() {
  userProfile.value.map(
    data: (profile) => print('Loaded profile: ${profile.name}'),
    error: (err, stack) => print('Error: $err'),
    loading: () => print('Fetching profile...'),
  );
});

// Updating userId automatically triggers a new asynchronous fetch
userId.value = 456;

References#

The computedFrom type is referenced and used in the following pages: