Last active
February 21, 2023 22:40
-
-
Save TekExplorer/d0381a8e18b5b8abc047c154dfe613af to your computer and use it in GitHub Desktop.
A potential mutation provider for riverpod
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'dart:math'; | |
| import 'package:flutter/material.dart'; | |
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | |
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | |
| part 'mutation_provider.g.dart'; | |
| class ExampleWidget extends ConsumerWidget { | |
| const ExampleWidget({super.key}); | |
| static Future<String> mockFunction() async { | |
| await Future.delayed(const Duration(seconds: 2)); | |
| if (Random().nextBool()) { | |
| throw Exception('Example Error'); | |
| } | |
| return 'Completed Mutation'; | |
| } | |
| @override | |
| Widget build(BuildContext context, WidgetRef ref) { | |
| final mutation = ref.watch(stringMutationProvider); | |
| return ListTile( | |
| leading: mutation.when( | |
| initial: () => null, | |
| loading: () => const CircularProgressIndicator(), | |
| success: (_) => const Icon(Icons.check), | |
| error: (_, __) => const Icon(Icons.error), | |
| ), | |
| title: const Text('Example Mutation'), | |
| subtitle: mutation.when( | |
| initial: () => const Text('Initial'), | |
| loading: () => const Text('Loading'), | |
| success: (data) => Text('Success: $data'), | |
| error: (error, _) => Text('Error: $error'), | |
| ), | |
| onTap: mutation.maybeWhen( | |
| // dont want to have it run multiple times at once | |
| loading: null, | |
| orElse: () { | |
| // onTap callback | |
| return () { | |
| mutation.call(mockFunction); | |
| }; | |
| }, | |
| ), | |
| ); | |
| } | |
| } | |
| // example mutation with an actual value result | |
| @riverpod | |
| Mutation<String> stringMutation(StringMutationRef ref) { | |
| return Mutation.initial(ref); | |
| } | |
| // generic mutation | |
| @riverpod | |
| Mutation<void> mutation(MutationRef ref, Object mutationKey) { | |
| return Mutation.initial(ref); | |
| } | |
| class Mutation<T> { | |
| const Mutation(this._ref, this.state); | |
| const Mutation.initial(this._ref) : state = null; | |
| final ProviderRef<Mutation<T>> _ref; | |
| final AsyncValue<T>? state; | |
| AsyncValue<T> _setState(AsyncValue<T> newState) { | |
| if (state != null) { | |
| newState = newState.copyWithPrevious(state!); | |
| } | |
| _ref.state = Mutation(_ref, newState); | |
| return newState; | |
| } | |
| Future<AsyncValue<T>> call(Future<T> Function() cb) async { | |
| _setState(AsyncValue<T>.loading()); | |
| final result = await AsyncValue.guard<T>(cb); | |
| return _setState(result); | |
| } | |
| bool get isInitial => state == null; | |
| bool get isLoading => state?.isLoading ?? false; | |
| bool get isSuccess => hasData; | |
| bool get hasData => state?.hasValue ?? false; | |
| bool get hasError => state?.hasError ?? false; | |
| } | |
| extension MutationX<T> on Mutation<T> { | |
| R when<R>({ | |
| bool skipLoading = false, | |
| bool skipError = false, | |
| required R Function() initial, | |
| required R Function() loading, | |
| required R Function(T data) success, | |
| required R Function(Object error, StackTrace stackTrace) error, | |
| }) { | |
| if (state == null) { | |
| return initial(); | |
| } | |
| return state!.when( | |
| skipLoadingOnRefresh: skipLoading, | |
| skipLoadingOnReload: skipLoading, | |
| skipError: skipError, | |
| data: success, | |
| loading: loading, | |
| error: error, | |
| ); | |
| } | |
| R maybeWhen<R>({ | |
| bool skipLoading = false, | |
| bool skipError = false, | |
| R Function()? initial, | |
| R Function()? loading, | |
| R Function(T data)? success, | |
| R Function(Object error, StackTrace stackTrace)? error, | |
| required R Function() orElse, | |
| }) { | |
| return when( | |
| skipLoading: skipLoading, | |
| skipError: skipError, | |
| initial: initial ?? orElse, | |
| loading: loading ?? orElse, | |
| success: (_) => success?.call(_) ?? orElse(), | |
| error: (_, __) => error?.call(_, __) ?? orElse(), | |
| ); | |
| } | |
| R? whenOrNull<R>({ | |
| bool skipLoading = false, | |
| bool skipError = false, | |
| R Function()? initial, | |
| R Function()? loading, | |
| R Function(T data)? success, | |
| R Function(Object error, StackTrace stackTrace)? error, | |
| }) { | |
| return maybeWhen( | |
| skipLoading: skipLoading, | |
| skipError: skipError, | |
| initial: initial, | |
| loading: loading, | |
| success: success, | |
| error: error, | |
| orElse: () => null, | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment