Snippets
A collection of copy-pasteable solutions to common development problems, ReArch style. Everything shown here is one way to solve the corresponding problem; there are likely other equally-valid solutions as well.
If you have any suggestions of snippets to add, please open a new issue here!
Sign In Flow
And how to relay the state of an asynchronous action in the UI while it occurs via "mutations."
/// Provides a [Random].
// NOTE: encapsulating this enables easy implementation switching later on.
Random randomCapsule(CapsuleHandle use) => Random();
/// Provides a function that signs the user in.
Future<void> Function(String, String) signInAction(CapsuleHandle use) {
// NOTE: we have this `use` call up top (before it is actually needed)
// because you must never use a CapsuleHandle across an asynchronous gap
// (which includes in a function callback (below) or after an await).
// But don't worry, ReArch will give you a reminder if you ever forget.
final random = use(randomCapsule);
return (email, password) {
// Dummy implementation that is fallible
return Future.delayed(const Duration(seconds: 1), () {
if (random.nextBool()) throw Exception('Sign in failed');
});
};
}
@rearchWidget
Widget signInForm(WidgetHandle use) {
final (email, setEmail) = use.state('');
final (password, setPassword) = use.state('');
final (state: signInState, mutate: mutateSignIn, clear: _) =
use.mutation<void>();
final rawSignIn = use(signInAction);
void signIn() => mutateSignIn(rawSignIn(email, password));
return Column(
children: [
TextField(onChanged: setEmail),
TextField(onChanged: setPassword),
ElevatedButton.icon(
icon: const Icon(Icons.person_rounded),
onPressed: signInState is AsyncLoading ? null : signIn,
label: const Text('Sign In'),
),
switch (signInState) {
null => const SizedBox.shrink(), // no sign-in attempted yet
AsyncData<void>() => const Text('Signed In'),
AsyncLoading<void>() => const CircularProgressIndicator(),
AsyncError<void>(:final error) => Text('$error'),
},
],
);
}