BloomMutation<T, P> class

Asynchronous mutation manager with automated optimistic updates, automatic rollback, and cache invalidation.

BloomMutation orchestrates side-effecting operations (such as HTTP POST, PUT, DELETE):

  • Optimistic Updates: Immediately writes anticipated state changes into the BloomData cache via optimisticData before the network response completes.
  • Automated Rollback: If the network call fails or throws, BloomMutation automatically reverts the cache entry at optimisticKey to its exact pre-mutation snapshot.
  • Cache Invalidation: Automatically calls BloomData.invalidateQueries for all keys in invalidateKeys upon successful completion, triggering background refetches in active BloomQuery instances.
  • Reactive Signals: Exposes data, status, and error as ReadonlySignal instances, allowing UI components to track loading and error states reactively.

Execution Flow

  1. status changes to MutationStatus.pending and error is cleared to null.
  2. If optimisticKey and optimisticData are set, snapshot current cache data and apply optimistic update.
  3. onMutate hook is executed; its returned value becomes the context.
  4. mutateFn is executed with the supplied parameters.
  5. On Success:
  6. On Error:

Backend Behavior

  • Browser (mount): Subscribed Live descriptors update reactively across pending, success, and error states.
  • SSR (renderToHtml): Safe to instantiate. Initial state is MutationStatus.idle.

Example

final createTodo = mutation<Todo, String>(
  mutate: (title) => httpClient.post<Todo>('/todos', body: {'title': title}),
  optimisticKey: ['todos'],
  optimisticData: (title, oldTodos) => [
    ...?oldTodos as List<Todo>?,
    Todo(id: 'temp-id', title: title, done: false),
  ],
  invalidateKeys: [['todos']],
  onError: (err, title, context) => print('Failed to add todo: $err'),
);

BloomNode buildAddTodoForm() {
  return Div(
    children: [
      Button(
        text: 'Create',
        on: {'click': (e) => createTodo.mutate('Buy groceries')},
      ),
      Live(() => createTodo.isPending ? Span(text: ' Saving...') : Span(text: '')),
    ],
  );
}

See also:

  • mutation, the convenience factory function for creating mutations.
  • BloomQuery, for managing cached queries that this mutation invalidates.
  • BloomData, the underlying cache manager.

Constructors

BloomMutation({required MutationFn<T, P> mutateFn, List? optimisticKey, OptimisticUpdater<T, P>? optimisticData, List<List> invalidateKeys = const [], OnMutateCallback<P>? onMutate, OnSuccessCallback<T, P>? onSuccess, OnErrorCallback<P>? onError, OnSettledCallback<T, P>? onSettled})
Creates a BloomMutation instance with execution hooks and cache invalidation targets.

Properties

data → ReadonlySignal<T?>
Reactive signal holding the latest successful result data, or null if unexecuted or failed.
no setter
error → ReadonlySignal<Object?>
Reactive signal holding the unhandled exception thrown during execution, or null if idle/successful.
no setter
hashCode → int
The hash code for this object.
no setterinherited
invalidateKeys → List<List>
List of query cache key prefixes invalidated upon successful mutation completion.
final
isError → bool
Whether the mutation failed with an error (MutationStatus.error).
no setter
isIdle → bool
Whether the mutation is in MutationStatus.idle status (unexecuted or reset).
no setter
isPending → bool
Whether the mutation is actively in-flight (MutationStatus.pending).
no setter
isSuccess → bool
Whether the mutation completed successfully (MutationStatus.success).
no setter
mutateFn → MutationFn<T, P>
The underlying asynchronous execution function performing the mutation.
final
onError → OnErrorCallback<P>?
Optional hook invoked when the mutation fails with an error.
final
onMutate → OnMutateCallback<P>?
Optional hook invoked immediately prior to executing the mutation.
final
onSettled → OnSettledCallback<T, P>?
Optional hook invoked when the mutation settles (either success or error).
final
onSuccess → OnSuccessCallback<T, P>?
Optional hook invoked upon successful mutation resolution.
final
optimisticData → OptimisticUpdater<T, P>?
Optimistic data transformation callback applied to the cache before network resolution.
final
optimisticKey → List?
Optional query cache key targeted for automated optimistic updates and rollback.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
status → ReadonlySignal<MutationStatus>
Reactive signal indicating the current lifecycle MutationStatus (idle, pending, success, error).
no setter

Methods

mutate(P params) → Future<T?>
Safely executes the mutation with params.
mutateAsync(P params) → Future<T>
Executes the mutation with params, returning the resolved data or rethrowing the caught error.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
reset() → void
Resets the mutation state back to MutationStatus.idle, clearing data and error to null.
toString() → String
A string representation of this object.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited