Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter BLoC `buildWhen` property

Tags:

flutter

dart

bloc

I get a _CastError error at the last line of this piece of code

BlocBuilder buildUsernameField() {
  return BlocBuilder<ProfileBloc, ProfileState>(
    buildWhen: (previous, current) => previous != current && current is EditingUserInfo,
    builder: (context, state) => TextField(
      keyboardType: TextInputType.name,
      controller: TextEditingController(
          text: (state as EditingUserInfo).username.value),

saying that

I/flutter (26787): The following _CastError was thrown building BlocBuilder<ProfileBloc, ProfileState>(dirty, state:
I/flutter (26787): _BlocBuilderBaseState<ProfileBloc, ProfileState>#25b87):
I/flutter (26787): type 'Success' is not a subtype of type 'EditingUserInfo' in type cast

So what's happening is that it tries to build that widget when I am in another state (success). But in the buildWhen parameter, I specified that the widget should only build when the state is EditingUserInfo.

So as far as I understand, this error should not happen.

Here's my ProfileState :

part of 'profile_bloc.dart';

abstract class ProfileState extends Equatable {
  const ProfileState();
  
  @override
  List<Object> get props => [];
}

class ProfileInitial extends ProfileState {}

class EditingUserInfo extends ProfileState {
  final Username username;
  final Bio bio;
  final PhotoUrl photoUrl;
  final City city;
  final FormzStatus status;

  const EditingUserInfo({
    this.username = const Username.pure(),
    this.bio = const Bio.pure(),
    this.photoUrl = const PhotoUrl.pure(),
    this.city = const City.pure(),
    this.status = FormzStatus.pure,
  });

  EditingUserInfo copyWith({Username username, Bio bio, PhotoUrl photoUrl, City city, FormzStatus status}){
    return EditingUserInfo(
      username: username ?? this.username,
      bio: bio ?? this.bio,
      photoUrl: photoUrl ?? this.photoUrl,
      city: city ?? this.city,
      status: status ?? this.status,
    );
  }

  @override
  List<Object> get props => [username, bio, photoUrl, city];
}

class Loading extends ProfileState {}

class Error extends ProfileState {
  final String message;

  const Error({this.message});

  @override
  List<Object> get props => [message];
}

class Success extends ProfileState {
  final String message;

  const Success({this.message});

  @override
  List<Object> get props => [message];
}

like image 563
user54517 Avatar asked Jun 20 '26 02:06

user54517


2 Answers

You still have to check that the state variable is the proper state. The state is checked EVERY time it is changed, so the state variable can still be a different state, it just doesn't rebuild unless the buildWhen conditions are true.

BlocBuilder buildUsernameField() {
return BlocBuilder<ProfileBloc, ProfileState>(
buildWhen: (previous, current) => previous != current && current is EditingUserInfo,
builder: (context, state) {
 if(state is EditingUserInfo) {
  return TextField(
  keyboardType: TextInputType.name,
  controller: TextEditingController(
      text: state.username.info)
}
}
like image 175
Scott Godfrey Avatar answered Jun 22 '26 02:06

Scott Godfrey


Here's a clear answer to your questioning user54517 :

buildWhen will prevent your widget to rebuild if the bloc state changes, but it will not prevent it if the framework rebuilds it for any other reason (for instance, if one of its parents need a rebuild...).

That's why you still need to check the state in the builder method.

Source: https://github.com/felangel/bloc/issues/1413#issuecomment-655568783

like image 27
Nicolas Avatar answered Jun 22 '26 01:06

Nicolas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!