How to manage different States in the same Bloc? Flutter
You are not passing num value on emit(ProductsTercero(msg: 'New msg'));
Since num == null then it is set to 0, as defined by your code.
Try Replacing like below
on<OnTercero>((event, emit) {
emit(ProductsTercero(msg: 'New msg',numero: 6));
});
Dubbain
Updated on December 16, 2022Comments
-
Dubbain over 1 year
I am trying to handle 3 different states in my app, in the initState of my home, I call the event "OnInitial" pretending to be a method that fetches data from the local DB.
As you can see in the method on I am setting "6" to the variable "number" as I said, pretending that this would be the data that I brought from the DB. My event finishes fetching the data and emits the state "ProductsTercero" already with "the data assigned".
In my home, if the state is ProductsTercero I paint a column with the "msg" and the "number". When inital finishes my screen is redrawn correctly and shows
But my problem is the following. When I press the button called "Tercero" that triggers the event "OnTercero" In my Bloc, when this event is called, it sets a 'New msg' to the variable "msg" of ProducsTercero. What does this? the next:
It removes the "number 6" that I had set before, that is, regarding the simulation, I would be deleting all the data that I brought from the DB.
my expected result was:
New msg 6
but i got
New msg 0
I debug and it seems like it's always creating a new ProductsThird object. even if I do ProductsTercero().copyWith(msg: 'New msg'); is the same.
I have worked with only 1 state and this does not happen to me, because I always do a state.copyWith(); and the other values of that state are always maintained no matter if i pass 1 attribute of 5 attributes it has. but here, having more than one state and having an abstract state class, I can't write emit(state.copyWith(msg: 'New msg');
What am I doing wrong? What would be the correct way to emit on X state and that this does not happen?
Event, state and bloc code:
part of 'products_bloc.dart'; @immutable abstract class ProductsEvent {} class OnInitial extends ProductsEvent {} class OnSegundo extends ProductsEvent {} class OnTercero extends ProductsEvent {} //**************************************************************// part of 'products_bloc.dart'; @immutable abstract class ProductsState {} class ProductsInitial extends ProductsState { final String? msg; final int? numero; ProductsInitial({numero, msg}) : msg = msg ?? 'MSG: Default Inicial', numero = numero ?? 0; ProductsInitial copywith({String? msg, int? numero}) => ProductsInitial(msg: msg ?? this.msg, numero: numero ?? this.numero); } class ProductsSegundo extends ProductsState { final String? msg; final int? numero; ProductsSegundo({numero, msg}) : msg = msg ?? 'Second: Default Msg', numero = numero ?? 0; ProductsSegundo copywith({String? msg, int? numero}) => ProductsSegundo(msg: msg ?? this.msg, numero: numero ?? this.numero); } class ProductsTercero extends ProductsState { final String? msg; final int? numero; ProductsTercero({numero, msg}) : msg = msg ?? 'Third: Default Msg', numero = numero ?? 0; ProductsTercero copywith({String? msg, int? numero}) => ProductsTercero(msg: msg ?? this.msg, numero: numero ?? this.numero); } //**********************************************************// import 'package:bloc/bloc.dart'; import 'package:meta/meta.dart'; part 'products_event.dart'; part 'products_state.dart'; class ProductsBloc extends Bloc<ProductsEvent, ProductsState> { ProductsBloc() : super(ProductsInitial()) { on<OnInitial>((event, emit) { emit(ProductsInitial().copywith( msg: 'Initial msg' )); emit(ProductsTercero(numero: 6)); }); on<OnSegundo>((event, emit) { emit(ProductsSegundo()); }); on<OnTercero>((event, emit) { emit(ProductsTercero(msg: 'New msg')); }); } }
Homepage code:
import 'package:bloc_test/src/bloc/products/products_bloc.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { @override void initState() { BlocProvider.of<ProductsBloc>(context).add(OnInitial()); super.initState(); } @override Widget build(BuildContext context) { return BlocBuilder<ProductsBloc, ProductsState>( builder: (context, state) { return Scaffold( body: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ (state is ProductsInitial) ? Column( children: [ Center(child: Text(state.msg!)), Center(child: Text(state.numero!.toString())), ], ) : (state is ProductsSegundo) ? Column( children: [ Center(child: Text(state.msg!)), Center(child: Text(state.numero!.toString())), ], ) : (state is ProductsTercero) ? Column( children: [ Center(child: Text(state.msg!)), Center(child: Text(state.numero!.toString())), ], ) : Center(child: Text('Nada')), SizedBox( height: 40, width: double.infinity, child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: <Widget>[ ElevatedButton( onPressed: () { BlocProvider.of<ProductsBloc>(context).add(OnInitial()); }, child: Text('Initial')), ElevatedButton( onPressed: () { BlocProvider.of<ProductsBloc>(context).add(OnSegundo()); }, child: Text('Segundo')), ElevatedButton( onPressed: () { BlocProvider.of<ProductsBloc>(context).add(OnTercero()); }, child: Text('Tercero')) ], ), ), ], ), ); }, ); } }
-
Dubbain over 2 yearsHi, yes but what about if i have an State with 10 variables? in a same situation I will have to pass each of the variables in each emit while I would really be changing 1 in the method. So i think your answer it's ok but is not the solution for this situation that i'm mentioning. Im still looking for a solution