Closed ctrlji closed 3 years ago
Hi @abolajimustapha 👋 Thanks for opening an issue!
I took a look and it looks like the problem is at https://github.com/abolajimustapha/apartmentplus/blob/eeb3b93b1be976c9a2252219e909372a31170893/lib/presentation/screens/authentication/verify/body.dart#L108.
First, you should make sure that when you are interacting with the cubit you are interacting with the same instance that is created. In this case you are creating an entirely different cubit and calling sendEmail
.
Second, you should never do this within the builder
. The builder
(and build
method) should have no side-effects. Instead I would recommend adding this event to the cubit when it is created.
BlocProvider(
create: (ctx) => VerifyCubit(verificationRepo)..sendEmail(this.widget.user),
child: Scaffold(...),
)
This will call sendEmail
as soon as the widget is mounted.
Hope that helps 👍
Hi Felix, thanks a lot. the issue has been resolved.
I also found out that to effect states emitted from blocbuilder the context.watch<Cubit>().function()
, in my case, context.watch<VerifyCubit>.sendEmail(user)
also works fine keeping the same instance of cubit across the widget tree. For the sake of developers with related issue, this video series on flutter bloc really helps a lot: https://www.youtube.com/watch?v=w6XWjpBK4W8&list=PLptHs0ZDJKt_T-oNj_6Q98v-tBnVf-S_o
Once again thanks!
Hi @abolajimustapha Thanks for opening an issue!
I took a look and it looks like the problem is at https://github.com/abolajimustapha/apartmentplus/blob/eeb3b93b1be976c9a2252219e909372a31170893/lib/presentation/screens/authentication/verify/body.dart#L108.
First, you should make sure that when you are interacting with the cubit you are interacting with the same instance that is created. In this case you are creating an entirely different cubit and calling
sendEmail
.Second, you should never do this within the
builder
. Thebuilder
(andbuild
method) should have no side-effects. Instead I would recommend adding this event to the cubit when it is created.BlocProvider( create: (ctx) => VerifyCubit(verificationRepo)..sendEmail(this.widget.user), child: Scaffold(...), )
This will call
sendEmail
as soon as the widget is mounted.Hope that helps
Sorry for replaying in a closed issue and I am going to as a noob question. How can we make sure to use same instance of bloc while we need to listen for state change from another bloc? I faced problem while listening to another bloc. After reading your comment I immediately made bloc a singleton and it worked. Is this only way and we need to use DI if we need to listen the state of a bloc from other bloc? or there is another workaround?
Am also having similar issue too. I have a Bloc that is yielding a state but the BlocConsumer failed to listen to the state change. Can anybody tell me what am doing wrong.
STATE CLASS:
part of 'people_bloc.dart';
@immutable abstract class PeopleState {}
class PeopleInitial extends PeopleState {}
class PeopleLoadingState extends PeopleState { @override List<Object?> get props => []; }
class SearchLoadingState extends PeopleState { @override List<Object?> get props => []; }
class NoReturnState extends PeopleState { final String? message;
NoReturnState({this.message});
@override List
class PeopleErrorState extends PeopleState { final int? status; final String? message;
PeopleErrorState({this.status, this.message});
@override List
class GetPeopleState extends PeopleState { final SearchPeopleResponse getPeopleResponse;
GetPeopleState({required this.getPeopleResponse});
@override List<Object?> get props => [getPeopleResponse]; }
class GetSearchResultState extends PeopleState { final SearchPeopleResponse getPeopleResponse;
GetSearchResultState({required this.getPeopleResponse});
@override List<Object?> get props => [getPeopleResponse]; }
EVENT CLASS:
part of 'people_bloc.dart';
@immutable abstract class PeopleEvent { const PeopleEvent(); }
class GetPeopleEvent extends PeopleEvent { final String term; GetPeopleEvent({required this.term}); @override List
class SearchPeopleEvent extends PeopleEvent { final String term; SearchPeopleEvent({required this.term}); @override List
BlOC:
class PeopleBloc extends Bloc<PeopleEvent, PeopleState> { final client = RestClient(Dio(BaseOptions(contentType: "application/json"))); PeopleBloc() : super(PeopleInitial());
@override void onTransition(Transition<PeopleEvent, PeopleState> transition) { super.onTransition(transition); print(transition); }
List
if (responseData.status == 200) {
yield GetSearchResultState(getPeopleResponse: responseData);
} else {
yield PeopleErrorState(message: responseData.msg);
print("loadingE");
}
} catch (e) {
//print("error msg here ${e.toString()}");
PeopleErrorState(message: e.toString());
}
}
if (event is GetPeopleEvent) {
try {
yield PeopleLoadingState();
var token = await getToken();
//print(token);
SearchPeopleResponse responseData =
await client.getPeople(token!, event.term);
if (responseData.status == 200) {
if (responseData.data.length == 0) {
yield NoReturnState(message: 'No Result');
} else {
yield GetPeopleState(getPeopleResponse: responseData);
}
} else if (responseData.status == 401) {
yield NoReturnState(message: responseData.msg); //no result
} else {
yield PeopleErrorState(message: responseData.msg);
}
} catch (e) {
//print("error msg here ${e.toString()}");
PeopleErrorState(message: e.toString());
}
}
}
MY STATEFUL CLASS:
class SearchPeopleScreen extends StatefulWidget { const SearchPeopleScreen({Key? key}) : super(key: key); static String routeName = 'search_people';
@override _SearchPeopleScreenState createState() => _SearchPeopleScreenState(); }
class _SearchPeopleScreenState extends State
List
void initState() {
Future.delayed(Duration.zero, () {
// _peopleBloc.add(
// GetPeopleEvent(term: ''),
// );
BlocProvider.of
@override Widget build(BuildContext context) { return BlocConsumer<PeopleBloc, PeopleState>( listener: (context, state) { print("Listener has been called"); if (state is GetSearchResultState) { loading = false; print("Result Found in view"); } else if (state is SearchLoadingState) { loading = true; print("Search loading"); } else if (state is PeopleLoadingState) { loading = true; } else if (state is GetPeopleState) { //print(state.getPeopleResponse.status); loading = false; data = state.getPeopleResponse.data; print("Am Here2"); } else if (state is NoReturnState) { loading = false; } else if (state is PeopleErrorState) { print("Am Here3"); loading = false; print(state.message); final snackBar = SnackBar(content: Text('state.message.toString()')); ScaffoldMessenger.of(context).showSnackBar(snackBar); } }, builder: (context, state) { return Container( child: Indexer( children: [ if (loading) Center( child: Container( width: 80.0, height: 80.0, child: SpinKitCircle( color: Colors.blue, size: 50.0, ), ), ), BlocProvider( create: (context) => PeopleBloc(), child: SingleChildScrollView( child: Container( height: 500.0, width: double.infinity, child: ListView.separated( separatorBuilder: (BuildContext context, int index) => Divider(height: 2), itemCount: data.length, itemBuilder: (context, index) { final people = data[index]; return GestureDetector( onTap: () async { Navigator.pushNamed( context, PeopleProfile.routeName, arguments: people.user_id); // Navigation.intentWithClearAllRoutes( // context, PeopleProfile.routeName); }, child: ListTile( title: Text( people.fullname, style: TextStyle(fontWeight: FontWeight.bold), ), subtitle: Text('@${people.username}'), leading: CircleAvatar( radius: 25, backgroundColor: Colors.grey, child: ClipRRect( borderRadius: BorderRadius.circular(50), child: Image.network( people.photo_path, width: 50, height: 50, fit: BoxFit.cover, ), ), ), trailing: MyButton( index: index, userID: int.parse(people.user_id)), ), ); }), ), ), ), ], ), ); }, ); }
Describe the bug Except the email verification screen of my flutter project, everything works fine. The BLOC for email verification screen & body does not emit changes in the cubit file when running code. I use this logic component methodology for other authentication screens like login and register screens and they work perfectly. But for some reasons I'm not sure of the email verification screen does not pick up on any state changes.
Steps to reproduce Here is the link to the full flutter project's public repository: https://github.com/abolajimustapha/apartmentplus/tree/main/
Scripts verify_mail_screen.dart : screen that gets navigated to from login or register screen on user click event
body.dart: a separate file that holds the main UI components the VerifyMail screen, where the magic of BlocConsumer listening is supposed to happen(but sadly does not).
In the Cubit Folder
verify_state.dart : holds classes for various states on function trigger
verify_cubit.dart : cubit file for the verify screen UI triggers functions but doesn't emit states
Logs No error logs of any sort even on flutter analyze
Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel stable, 1.22.4, on Microsoft Windows [Version 10.0.18362.175], locale en-US)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.2) [√] Android Studio (version 4.0) [√] VS Code (version 1.51.1) [√] Connected device (1 available)