Bloc: BlocBuilder does not receive the state

Created on 1 Oct 2020  路  3Comments  路  Source: felangel/bloc

Hi! I'm new with flutter and I'm writing a simple app: there is an items' list and under this a TextForm to insert a new element, i type the name and click the button "add", and the element is written in firestore. This part works fine, but after this i need to reload the list to show the new element, and this is where i've the problem: i know that i can't yield the same state twice, so i yield first LoadingState (that is empty) and then LoadedListState, but the blocBuilder doesn't receive anything, i also inserted a print. I'm using flutter_bloc: 6.0.5, with older versions (4..) i didn't have this problem. What am i doing wrong?

firebaseBloc.dart

    @override
    Stream<FirebaseState> mapEventToState(FirebaseEvent event, ) async* {

    print("event firebase ${event.runtimeType.toString()}");

    if (event is CreateItemFirebaseEvent) {
      yield LoadingState();
      await _databaseService.createItem(event.item, event.user);
      List<Item>itemsList = await _databaseService
          .loadItemsList(event.user.itemsIDsList);
      yield LoadedItemsListState(itemsList);
    }

    if (event is LoadItemsListEvent) {
      List<Item> itemsList =
          await _databaseService.loadItemsList(event.ItemsIDs);
      yield LoadedItemsListState(itemsList);
    }

firebase_state.dart

abstract class FirebaseState extends Equatable {
  const FirebaseState();
}

class LoadingState extends FirebaseState {
  @override
  List<Object> get props => [];
}

class LoadedItemsListState extends FirebaseState {
  final List<Item> itemsList;

  LoadedItemsListState(this.itemsList);

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

screen_widget.dart

class ItemSelectionScreen extends StatefulWidget {
  final User user;

  ItemSelectionScreen({
    @required this.user,
  });

  @override
  _ItemSelectionScreenState createState() =>
      _ItemSelectionScreenState();
}

class _ItemSelectionScreenState extends State<ItemSelectionScreen> {
  FirebaseBloc _firebaseBloc;

  @override
  void initState() {
    super.initState();

    _firebaseBloc = FirebaseBloc();
    _firebaseBloc.add(LoadItemsListEvent(widget.user.itemsIDsList));
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider<FirebaseBloc>(
      create: (context) => _firebaseBloc,
      child: Scaffold(
        body: SingleChildScrollView(
          child: Center(
            child: BlocBuilder(
              cubit: _firebaseBloc,
              builder: (context, state) {
                print("state ${state.runtimeType.toString()}");

                if (state is LoadedItemsListState) {
                  return buildUI(state);
                } else if (state is LoadingState) {
                  return CircularProgressIndicator();
                } else {
                  return _CreateItemFormWidget(widget.user);
                }
              },
            ),
          ),
        ),
      ),
    );
  }

  Column buildUI(LoadedItemsListState state) {
    return Column(
      children: [
        _CreateItemFormWidget(widget.user),
        ListView.builder(
          itemBuilder: (context, index) {
            return Container(
              color: Colors.amber,
              child: ListTile(
                trailing: Text(
                  ">",
                  style: TextStyle(fontSize: 20),
                ),
                onTap: () => null,
                title: Text(state.itemsList[index].name),
              ),
            );
          },
          shrinkWrap: true,
          itemCount: state.itemsList.length,
        ),
      ],
    );
  }
}

i also inserted prints, when load page the first time, the output is:

state InitialFirebaseState
event firebase LoadItemsListEvent
state LoadedItemsListState

and then, when i click add:

event firebase CreateItemFirebaseEvent

and it doesn't print anything about states. I also have inserted debug points, but it doesn't stops...

I also made this experiment: yield a WaitinState(empty state) instead of LoadedListState, and it is received. My theory is that the blocBuilder receive only the latest state when i yield more than one, and this state is LoadedListState, so it's ignored becouse is equal to the previuos state received.

What can i do to resolve?

Thanks in advance

question

Most helpful comment

Hi @Ozymandias93 馃憢

As @alfredobs97 pinpointed, you have pass all your props to equatable for the value equality to properly work.

class LoadedRestaurantsListState extends FirebaseState {
  final List<Restaurant> restaurantsList;

  LoadedRestaurantsListState(this.restaurantsList);

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

Your Restaurant should also extend Equatable.

All 3 comments

Hi! You have to complete the getter of props to allow Bloc difference between same States or Events. I think this is the bug :)

Hi @Ozymandias93 馃憢

As @alfredobs97 pinpointed, you have pass all your props to equatable for the value equality to properly work.

class LoadedRestaurantsListState extends FirebaseState {
  final List<Restaurant> restaurantsList;

  LoadedRestaurantsListState(this.restaurantsList);

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

Your Restaurant should also extend Equatable.

thanks guys <3

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rsnider19 picture rsnider19  路  3Comments

krusek picture krusek  路  3Comments

craiglabenz picture craiglabenz  路  3Comments

1AlexFix1 picture 1AlexFix1  路  3Comments

komapeb picture komapeb  路  3Comments