0 purchases
ui actionable bloc
ui_actionable_bloc #
🎬 A mixin on Bloc that allows to perform UI actions and get results back.
Getting started #
Install the package #
dependencies:
ui_actionable_bloc: ^0.0.2
copied to clipboard
Add the mixin #
class LoginCubit extends Cubit<LoginCubitState> with UiActionableBlocMixin<LoginCubitState, LoginAction> {
...
}
copied to clipboard
Add a listener #
/// Somewhere in the UI, under the BlocProvider of LoginCubit:
@override
Widget build(BuildContext context) {
return BlocActionsListener<LoginCubit, LoginCubitState, LoginAction>(
listener: (context, state, action) {
// Handle LoginAction here!
},
child: ...,
);
}
copied to clipboard
Emit actions! #
Future<void> login() async {
try {
final user = await _loginUseCase();
emitUiAction(LoginAction.navigateHome(user));
// This 👆 will trigger the `listener` callback from above.
} catch (e, s) {
// Handle error
}
}
copied to clipboard
Passing the result back to the Bloc #
You can pass the result of the UI action back to the Bloc. For example, you can show an OTP pop up or a new route with text input after sending an OTP:
Await the result of emitUiAction:
await _sendOtpUseCase();
// Otp will land here once the action is completed in a listener!
final otp = await emitUiAction(OtpAction.requestOtpInput(user));
if (otp is! String) {
/// User did not input the OTP.
return;
}
await _validateOtpUseCase(otp);
copied to clipboard
Use BlocActionsListener.completable that has a slightly different listener callback:
@override
Widget build(BuildContext context) {
return BlocActionsListener<OtpCubit, OtpCubitState, OtpAction>.completable(
listener: (context, state, action, actionCompleter) {
final otpInput = await Navigator.of(context).push(OtpInputRoute());
// This will complete the emitUiAction future.
actionCompleter(otpInput);
},
child: ...,
);
}
copied to clipboard
FAQ #
Why? #
Sometimes we need to perform a UI action in the middle of a Bloc method. For example, get user input, like an OTP code after sending an SMS. Usually BlocListeners help us with this. We listen to a change in the state and, based on certain condition, we perform a UI action. We need several methods to do this: one for triggering an OTP, another for completing the flow after the OTP is entered.
However, it is not always convenient. What do we do with the data in the state after a UI action is performed? What if it will be accessed after a UI action is performed? Do we need to clear it beforehand or let it remain there? It is unclear because these actions depend on the same data that is used by the UI.
Although it can be resolved with one-time UI Actions.
Does it work with Cubits? #
Yes, it works with both Blocs and Cubits.
How is BlocActionsListener different from BlocListeners? #
BlocListeners work with Bloc.states while BlocActionsListener listens to actions emitted by emitUiAction.
Where do I put a BlocActionsListener? #
BlocActionsListener can be used in the same way as regular BlocListeners are used. You can even add BlocActionsListeners to a MultiBlocListener.
What if I don't complete an emitted action? #
For regular BlocActionsListener, you don't have to worry about completing an action. It emitUiAction is immediately completed with a null in this case. For BlocActionsListener.completable though, make sure you complete your action with some result. Otherwise it will be stuck.
Actions received by a BlocActionsListener will be automatically completed when this listener is disposed.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.