mutate method

Future<TData?> mutate(
  1. TVariables variables, {
  2. void onSuccess(
    1. TData data,
    2. TVariables variables
    )?,
  3. void onError(
    1. Object error,
    2. TVariables variables
    )?,
  4. void onSettled(
    1. TData? data,
    2. Object? error,
    3. TVariables variables
    )?,
})

Execute the mutation.

You can provide call-time callbacks onSuccess, onError, and onSettled which will run after the mutation-level callbacks defined in the constructor.

Implementation

Future<TData?> mutate(
  TVariables variables, {
  void Function(TData data, TVariables variables)? onSuccess,
  void Function(Object error, TVariables variables)? onError,
  void Function(TData? data, Object? error, TVariables variables)? onSettled,
}) async {
  if (isDisposed) {
    throw StateError('Mutation has been disposed');
  }

  // Reset state
  status.value = ZenMutationStatus.loading;
  _isLoadingNotifier?.value = true;
  error.value = null;
  update();

  Object? context;

  try {
    // Lifecycle: onMutate
    if (onMutate != null) {
      context = await onMutate!(variables);
    }

    // Execute mutation
    final result = await mutationFn(variables);

    if (isDisposed) return null;

    // Update state: Success
    data.value = result;
    status.value = ZenMutationStatus.success;
    _isLoadingNotifier?.value = false;
    update();

    // Lifecycle: onSuccess (Definition)
    this.onSuccess?.call(result, variables, context);
    // Lifecycle: onSuccess (Call-time)
    onSuccess?.call(result, variables);

    // Lifecycle: onSettled (Definition)
    this.onSettled?.call(result, null, variables, context);
    // Lifecycle: onSettled (Call-time)
    onSettled?.call(result, null, variables);

    return result;
  } catch (e) {
    if (isDisposed) return null;

    // Update state: Error
    error.value = e;
    status.value = ZenMutationStatus.error;
    _isLoadingNotifier?.value = false;
    update();

    // Lifecycle: onError (Definition)
    this.onError?.call(e, variables, context);
    // Lifecycle: onError (Call-time)
    onError?.call(e, variables);

    // Lifecycle: onSettled (Definition)
    this.onSettled?.call(null, e, variables, context);
    // Lifecycle: onSettled (Call-time)
    onSettled?.call(null, e, variables);

    // We generally don't rethrow here to prevent breaking UI event handlers,
    // as the error state is captured in the reactive variable.
    // If the caller awaits .mutate(), they can check .isError
    return null;
  }
}