flutterflutter-bloc

Can I use BloC with only one state and not emitting new ones?


I needed to keep variables across few pages. I created Cubit class for this, but in my thinking I didn't needed any state for this as my widgets doesn't depends on anything. I just need to keep data across pages to use it on the end.

MainPage -> PageA -> PageB -> PageC -> PageD -> Summary

User in Pages selecting some data, I need to store this, keep info what was selected if user is going back and forward to change and send this to API in Summary.

Here is how it looks:

class ParametersCubit extends Cubit<ParametersState> {
  ParametersCubit() : super(ParametersStateInitial());

  BoxParams? boxParams;
  bool? privateRentier;

  Map<dynamic, int> mapOfSelectedIds = {};
  Map<dynamic, BoxSize?> mapOfSizes = {};
  Map<dynamic, Variants> mapOfVariants = {};

  DateTime selectedDate = DateTime.now();
  DateTime? selectedRangeDate = DateTime.now().add(Duration(days: 14));

  void initParameters(BoxParams selectedBox, bool? privRentier) {
    clearParameters();
    boxParams = selectedBox;
    privateRentier = privRentier;
  }

  void setMapParameters(Map<dynamic, int> ids, Map<dynamic, BoxSize?> sizes, Map<dynamic, Variants> variants) {
    mapOfSelectedIds = ids;
    mapOfSizes = sizes;
    mapOfVariants = variants;
  }

  void clearParameters() {
    boxParams = null;
    privateRentier = null;
    mapOfSizes = {};
    mapOfSelectedIds = {};
    mapOfVariants = {};
    selectedDate = DateTime.now();
    selectedRangeDate = DateTime.now().add(Duration(days: 14));
  }

  void rentBox() {
    //TODO send request to API
  }
}

and here is my state class:

abstract class ParametersState {}

class ParametersStateInitial extends ParametersState {}

but I don't use any state actually.

Here is how I access this parameters in my code:


class SelectDate extends StatefulWidget {
  const SelectDate({Key? key}) : super(key: key);

  @override
  State<SelectDate> createState() => _SelectDateState();
}

class _SelectDateState extends State<SelectDate> {


  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    final local = AppLocalizations.of(context)!;
    return Scaffold(
      body: SafeArea(
        child: MainPadding(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                'From when you want to rent?',
                style: TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.w600,
                    color: Color(0xFF1B1B1B)
                ),
              ),
              const SizedBox(height: 64),
              CalendarDatePicker2(
                config: CalendarDatePicker2Config(
                  calendarType: CalendarDatePicker2Type.single,
                  firstDayOfWeek: 1,
                  firstDate: DateTime.now(),
                  weekdayLabels: [
                    local.sunday,
                    local.monday,
                    local.tuesday,
                    local.wednesday,
                    local.thursday,
                    local.friday,
                    local.saturday,
                  ]
                ),
                value: [
                  context.watch<ParametersCubit>().selectedDate
                ],
                onValueChanged: (date) {
                  context.read<ParametersCubit>().selectedDate = date.single;
                },
              )
            ]
          ),
        ),
      ),
    );
  }
}

and I have few pages more, using this Cubit class and context.read() to access variables and set them.

It's working as expected actually but I guess it's not how Cubit or Bloc should be used.

So my question is that I should create states, which I don't think I need here or there is other solution that I should use in my case or maybe my solution is not wrong at all?

I hope someone will explain me right way to do this as I am really worrying about this even this is working, but I don't want to code in wrong way.


Solution

  • If you are using context.watch<ParametersCubit>() somewhere on the page then this mean that UI on this page should be changed according to this value changes and your page depend on this value. In this case you are using cubit/bloc and this is correct. What is not good here - properties in the cubit. You should store all this values in the state.

    But if you don't need to listen to changes in the variables of your assembled model and change the state of your UI accordingly, then using a cubit/block is probably redundant. In this case, as an option, you can keep this data (model) in a repository, to which you will have access on each page.