I'm new to flutter BloC and I'm confused about its state usage. From the counter app, I built another basic app to show a different widget based on its state. But not sure how to do that.
Cubits:
part 'home_bloc_state.dart';
class HomeBlocCubit extends Cubit<HomeBlocState> {
HomeBlocCubit() : super(HomeBlocInitial());
void showHome() {
emit(HomeBlocInitial());
}
void showStudents() {
emit(HomeBlocStudents());
}
}
//state
part of 'home_bloc_cubit.dart';
@immutable
abstract class HomeBlocState {}
class HomeBlocInitial extends HomeBlocState {}
class HomeBlocStudents extends HomeBlocState {}
With a button widget I can add/toggle events:
final myBloc = BlocProvider.of<HomeBlocCubit>(context);
return Container(
child: ElevatedButton(
onPressed: () {
myBloc.showHome();
},
child: Text('Home'),
), )
To show events on UI I would like to return a Text widget based on state.
@override
Widget build(BuildContext context) {
return Container(child: Align(child:
BlocBuilder<HomeBlocCubit, HomeBlocState>(
builder: (context, state) {
//do something based on state.
//How to check or compare or get data from this state?
switch (state) {
case HomeBlocState: //error, - how to use?
break;
}
return Text(
"Welcome to this page: " + state.toString(),
style: TextStyle(
fontSize: 60 ),
);
})));
}
How to show UI based on state?
With Dart 3 you may leverage pattern matching and sealed classes. Now it is possible to change state
like that:
sealed class HomeBlocState {}
class HomeBlocInitial extends HomeBlocState {}
class HomeBlocStudents extends HomeBlocState {}
and use pattern matching in the builder:
return switch(state) {
HomeBlocInitial() => LoadingView(),
HomeBlocStudents() => StudentsList(),
};
You may check whether state
is in a required state by calling
if (state is HomeBlocInitial) {
...
}
If you prefer switches:
switch (state.runtimeType) {
case HomeBlocInitial:
return const HomeInitial();
default:
// probably throw
return const SizedBox();
}
A more mature approach (if you're good with code generation) would be to use freezed for states. In that case, your state would be declared as:
@freezed
class HomeBlocState with _$Failfast{
const factory HomeBlocState.initial() = _Initial;
const factory HomeBlocState.students() = _Students;
}
And inside BlocBuilder
you'll have:
return state.map(
initial: (initialState) => ...,
students: (studentsState) => ...,
);