mutate method
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;
}
}