How to manage different States in the same Bloc? Flutter

807

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));
});
Share:
807
Dubbain
Author by

Dubbain

Updated on December 16, 2022

Comments

  • Dubbain
    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

    enter image description here

    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:

    enter image description here

    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
    Dubbain over 2 years
    Hi, 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