Bloc: Await bloc.add

Created on 30 Jul 2020  路  14Comments  路  Source: felangel/bloc

For many reasons it would be awesome if we could wait for the bloc to finish with the event before continuing.

Here's an example

Future<void> testBloc(
) async {
  final data = await request('fetch-user');
  final user = UserV1.fromJson(data);
  // Bloc is access via static reference, it has to be this way.
  userBloc.add(UpdateUserAction(user));

  // Fails because it needs userBloc.state.user.uid
  fetchAllLogs();
}

I can't seem to find a solution or feature for it. If anyone knows it would be great.

question

Most helpful comment

await userBloc.first would wait for the next state. If you're yielding multiple states for a single event you need to do firstWhere

All 14 comments

Hi @ollydixon 馃憢

Why not invoke fetchAllLogs in the UpdateUserAction handler ? e.g.:

if (event is UpdateUserAction) {
  // process event
  fetchAllLogs();
}

@RollyPeres fetchAllLogs also has a logsBloc with add. :-/ I'm sort of stuck here; thanks for the reply.

fetchAllLogs has to finish and await and add before continuing.

Hi @ollydixon 馃憢
Thanks for opening an issue!

If you really need to do this you can do

userBloc.add(UpdateUserAction(user));

final nextState = await userBloc.first;

fetchAllLogs();

But this is usually not the best solution and is likely an indication that the flow of data can be reworked/simplified.

@felangel thank you so much! I've been stuck on this all day.

@felangel it would seem that the state is still invalid even after the await.

For example.

await userBloc.first;
userBloc.state.logs << 0

But if I wait for a second then run it again, userBloc.state.logs is 151.

Hmm stumped.

await userBloc.first would wait for the next state. If you're yielding multiple states for a single event you need to do firstWhere

@felangel I'm guessing firstWhere will just return the next state that was just added? (Matching the bool)

@ollydixon yup 馃憤

Closing this for now but feel free to comment with additional questions and I'm happy to continue the conversation 馃憤

@felangel thanks :-)

Would you ever consider adding await bloc.add to guarantee a consistent API for say 'next' event processes. Just an idea; maybe I sound dumb.

Great job on this lib btw. We deleted all our Redux from over 30 Flutter projects at my company.

@ollydixon I would like to avoid that because add is part of the Sink api which does not return a Future and also it would be confusing because a single add can result in multiple state changes so you would never know when the event was actually "done" being processed.

@felangel makes sense. I guess it's never reliable to assume values from distant state anyhow. Sticking to the firstWhere seemed to work perfect for our auth fetching scenarios. :-)

You can accomplish this more easily using Cubit (in v6.0.0 of bloc)

class MyCubit extends Cubit<MyState> {
  MyCubit() : super(MyState.initial());

  Future<void> doSomething() async {
    emit(MyState.loading());
    final result = await _repository.getResult();
    emit(MyState.success(result));
  }
}

Then you can await doSomething directly:

final cubit = MyCubit();
await cubit.doSomething();
print(cubit.state); // MyState.success

Hope that helps and thanks so much for the positive feedback -- I really appreciate it 馃檹

Thanks, I'll look into this; little abstract for my brain haha; most of our state/actions are in order, the stream stuff always confuses my coders.

For example it's as simple as:

Future<UserV1> updateUser(Map<String, dynamic> data) async {
  try {
    final json = await request('update-user', data: data);
    final user = UserV1.fromJson(json);
    userBloc.add(UpdateUser(user));
    return updatedUser;
  } catch (e) {
    print('Error updating user');
    print(e);
    throw e;
  }
}

The the UI handles the rest. Errors are handled directly and not in state management. We like as little code as possible! :-)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fvisticot picture fvisticot  路  31Comments

windinvip picture windinvip  路  39Comments

mariaszek9003 picture mariaszek9003  路  29Comments

pczn0327 picture pczn0327  路  67Comments

nosmirck picture nosmirck  路  30Comments