How to handle errors with ValueNotifier
265
Well, probably not the most optimal, but the solution I gave to this problem was to create a second valueNotifier to propagate custom exceptions as:
abstract class CustomException implements Exception {
final String message; // Note that this message is for logging not displaying to the user
CustomException(this.message);
}
class ExampleAuthException extends CustomException {
final int remainingAttempts;
ExampleAuthException({required this.remainingAttempts, required String message}) : super(message);
}
class ErrorNotifier extends ValueNotifier<CustomException?> {
ErrorNotifier(CustomException? value) : super(value);
}
class ViewState{
final ErrorNotifier errorNotifier;
final LoginStateNotifier loginState;
...
}
I make it nullable as to now when there are no errors, and I use this as a second communication channel.
Author by
Darrell
Updated on December 22, 2022Comments
-
Darrell over 1 year
I have a
ValueNotifier
class that performs some logic, then alerts all listeners when done. The problem I have is how to alert the listeners when there is an error in the processing so that an appropriate message can be displayed in the UI.Here is the
ValueNotifier
class:class LoginStateNotifier extends ValueNotifier<LoggedInStates> { LoginStateNotifier(LoggedInStates value) : super(value); Future<void> login({required String email, required String password}) async { try { final userCredential = await FirebaseAuth.instance .signInWithEmailAndPassword(email: email, password: password); print(userCredential); } on FirebaseAuthException catch (e) { switch (e.code) { case "invalid-email": throw (Constants.invalidEmail); case "user-disabled": throw (Constants.userDisabled); case "user-not-found": throw (Constants.userNotFound); case "wrong-password": throw (Constants.wrongPassword); default: throw ("${e.code} is an invalid FirebaseAuth exception"); } } catch (e) { throw ("DEBUG: ${e.toString()} - occurred in login()"); } } Future<void> logOut() async { await FirebaseAuth.instance.signOut(); } }
Here is the widget in the UI that is listening for changes:
ValueListenableBuilder<LoggedInStates>( valueListenable: _loginScreenController.loginStateNotifier, builder: (context, loggedInStates, child) { return loggedInStates == LoggedInStates.loggedIn ? Text( 'Logged In', style: Theme.of(context).textTheme.headline2, ) : Text( 'Logged Out', style: Theme.of(context).textTheme.headline2, ); }, ),
I just need a way for the listener to know when errors occur as well, not just when the value changes.
-
Darrell almost 3 yearsthanks a lot. that worked. but, i wonder if there is a solution that doesn't require another notifier, such as what's used in pub.dev/packages/error_notifier_for_provider?
-
croxx5f almost 3 yearsWell other solutions that come to my mind are using streams or futures that communicate errors or using discriminated unions like Either or Result (see dartz) that model an
object
as having two possible states and you could use something like Either<LoggedInStates,CustomException> as the value of your notifier. What are your thoughts on this @Darrell -
Darrell almost 3 yearsThis is my first Flutter app, so those solutions seem fairly complex and what you provided is easily understood and work. So, I will continue with your original solution for now and make note of the others for future reference as my experience grows.