Describe the bug
I have an event that dispatches EmailDeleted event with the email to be removed. The state is not getting updated after the email is removed from the list and pushing new state.
My mapEventToState method
@override
Stream<InviteState> mapEventToState(
InviteState currentState,
InviteEvent event,
) async* {
if (event is ScreenInitialized) {
final List<String> _emails = [];
yield EmailListUpdated(emails: _emails);
}
if (event is EmailSubmitted && currentState is EmailListUpdated) {
if (!isEmail(event.email)) {
yield currentState.copyWith(error: 'Please enter a valid email');
} else {
yield EmailListUpdated(emails: currentState.emails + [event.email]);
}
}
if (event is EmailDeleted && currentState is EmailListUpdated) {
yield EmailListUpdated(emails: currentState.emails..remove(event.email));
}
}
The following piece of code is supposed to remove the email passed in the event and map the new state but it isn't working.
if (event is EmailDeleted && currentState is EmailsListUpdated) {
yield EmailsListUpdated(emails: currentState.emails..remove(event.email));
}
It works only if I remove extending Equatable or trigger another event with a different state and then trigger the delete event. Even in that case it will identify the change only for the first removal and ignores all changes thereafter.
Do you see any problem with the code? Any help will be highly appreciated. Thanks in advanve!
@abinvp thanks for opening this!
I think in order to understand why it's not working you need to understand two things:
First, if you yield the same state over and over it will not impact a Bloc (meaning no transition will occur and the UI won't be rebuilt). In your case, you are yielding the same event multiple times (EmailsListUpdated(emails: ...)).
The second part is why it works without Equatable.
It works without Equatable because by default two different instances will not be equal:
print(EmailsListUpdated(emails: []) == EmailsListUpdated(emails: [])); // false
In order to make the above statement true you would use Equatable or override == and hashCode yourself.
So when writing blocs and yielding states you need to keep in mind if you yield state where state == currentState then nothing will happen because from the bloc's perspective nothing has changed.
Let me know if that helps 馃憤 and really good question! I'm planning to create an FAQs section of the bloc library documentation and will be sure to include this 馃槃
If you are still having trouble and can give me access to your code then I can try to open a PR.
@felangel, thank you for your response. Your response time is quite impressive :)
Even though I was yielding the same state, the emails list is modified. Just like EmailListUpdated(emails: currentState.emails + [event.email]) for add events, I was expecting EmailListUpdated(emails: currentState.emails..remove(event.email)); to work.
Thanks haha 馃槃
Is it possible for you to share a project that has the problem you're seeing? It'll be easier for me to help if I can have access to the full source code 馃憤
It doesn't have to be a real project; it could just be a tiny sample with the bare minimum to reproduce the issue you're seeing.
Yes, I will get that shortly. Thank you!
Hey @felangel,
I've pushed the code here. https://github.com/abinvp/flutter_bloc_package_demo
You can see a simple screen where users can be invited using the emails. The invited user's email will be displayed as chips in the UI. On clicking the close icon in the chip, that particular email should be removed and the UI should be updated. As you can see, the add part is working but delete isn't working.
@abinvp I've created a PR to fix your issue. It was because you were mutating the list of emails instead of creating a new list.
Bloc is built on the assumption that all state is immutable so you need to ensure that you are always creating new instances of state (all parts) instead of modifying the currentState.
Hope that helps! 馃憤
Makes total sense @felangel. That was an overlook from my side. Thank you so much for helping out and writing this wonderful package. 馃憤
No problem! It was a great question and evidence that I need to continue to improve the documentation 馃槄. Thanks for the positive feedback; I really appreciate it! 馃憤
@felangel dude ur awsome !!! thanks a lot
Hi I am using flutter_bloc package, at signing page while I am using Signin() instead of splash screen then redirecting working fine. but if use splash screen then login screen not redirecting to home. https://cl.ly/9be9be5eb844
@pardipbhatti8791 can you share a link to the repo? It would be much easier for me to help if I could run the application locally 馃憤
Most helpful comment
@felangel dude ur awsome !!! thanks a lot