Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter - BloC Cubit function doesn't emitting state

I'm creating a Flutter application. I'm added a BloC to my project for management state. I created a list with data. And I want to add item to ListView manually with button 'Add'.

I'm wrote a code:

My Item Cubit

class ItemCubit extends Cubit<List<Item>> {
  ItemCubit() : super([]);

  void addItem(item){
    state.add(item);
    emit(state);
  }
}

Page of Items with Provider:

class SearchPage extends StatelessWidget {
  const SearchPage({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider(
        create: (_) => ItemCubit(),
        child: Search(),
      ),
    );
  }
}

And I call the BlocBuilder in Stateless Widget like this:

body: BlocBuilder<MarketCubit, List<Market>>(
            builder: (context, items) => TabBarView(...))

So when I call my function from state:

Item item = Item(1, 'Item 1');


ElevatedButton(onPressed:(){
  context.read<ItemCubit>().addItem(item);
 }, child: Text('Add Item')),

The ListView doesn't updating. What's problem? Thanks a lot!

like image 250
user467566 Avatar asked Aug 25 '26 05:08

user467566


2 Answers

The problem is that you are just adding the item to the state and re-emitting the same (modified) list. Bloc will essentially check the value of the state object to see if it is a new object when you call emit(), if it is the 'same list' as the last state, it will do nothing. It is confusing because even though you are adding a new value to the list, it is still the same object in a sense, just with a new value.

So there should be an easy fix if you just create a new list instead of modifying the original one and emit that.

For example, this should fix the issue:

emit([...state, newValue])

or

final newList = List.from(state)..add(newValue);
emit(newList);

(I had trouble finding in the bloc documentation where this is explained, but there are a number of issue threads where it is discussed -https://github.com/felangel/bloc/issues/2374)

Essentially, the state should be 'immutable', so if you are going to emit a new state, you should actually create a new instance of whatever you are going to emit. The way I typically use the state is to have a class with final fields for whatever state the cubit is tracking, and a copyWith method that makes it easy to create a new instance with any modified fields:

YourCubitState{
    final List stateList;
    final otherField;

    const YourCubitState({
        this.stateList = [], 
        this.otherField,
    }); 

    YourCubitState copyWith({
        List? stateList,
        otherField,
    }) => 
        YourCubitState(
           stateList: stateList ?? this.stateList,
           otherField: otherField ?? this.otherField,
        );   

}

Maybe that is unnecessary if the state is just a single list, but if you find yourself wanting to add properties to the state, that is a good pattern to follow.

like image 103
Kris Avatar answered Aug 26 '26 22:08

Kris


create new variable, add them to the new variable list, update your new variable list item to it, emit the data with the new variable. this is how i got it working.

late List<ServicesExpensesList> newList = <ServicesExpensesList>[];
    state.utilityDataList.forEach((element) {
      newList.add(element);
    });
    newList.insert(0, utilityData);
    newList.sort((a, b) => b.createdAt.compareTo(a.createdAt));
    emit(state.copyWith(
      utilityDataList: newList,
      status: state.status == BlocStateStatus.success
          ? BlocStateStatus.updated
          : BlocStateStatus.success,
    ))
like image 25
miloth Avatar answered Aug 26 '26 22:08

miloth



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!