skip to Main Content

I am continuing a Flutter project of mine after quite some time and I no longer understand why a very basic pattern works.

As far as I remember and what I understand from the documentation, I need a BlocBuilder to update a screen upon a state change. However, my app also updates the screen without a BlocBuilder upon calling a Cubit function. So when I click on a navigation tab, the other page in the stack appears on front.

Why is this, even though I am only working with StateLessWidgets and no BlocBuilder?

class HomePageClient extends StatelessWidget {
  const HomePageClient({super.key});

  @override
  Widget build(BuildContext context) {
  return BlocProvider<HomeCubitClient>(
     create: (_) => HomeCubitClient(),
     child: HomeViewClient(nextJobsBloc: nextJobsBloc,
        specialTasksBloc: specialTasksBloc),);
  }
}

class HomeViewClient extends StatelessWidget {
  String? clientId;
    @override
  Widget build(BuildContext context) {
    final selectedTab = context.select((HomeCubitClient cubit) => cubit.state.tab);
    clientId = context.select((AppBloc bloc) => bloc.state.client!.clientId);
    return Scaffold(
      body: IndexedStack(
        index: selectedTab.index,
        children: [
          HomeMainClient(),
          PropertyListPage(clientId: clientId),
        ],

      ),
      bottomNavigationBar: BottomAppBar(
        shape: const CircularNotchedRectangle(),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            _HomeTabButton(
              groupValue: selectedTab,
              value: HomeTabClient.home,
              label: 'HOME',
            ),
            _HomeTabButton(
              groupValue: selectedTab,
              value: HomeTabClient.properties,
              label: 'PROPERTIES',
            ),
          ],
        ),
      ),
    );
  }
}

class _HomeTabButton extends StatelessWidget {
  const _HomeTabButton({
    required this.groupValue,
    required this.value,
    required this.label,
  });

  final HomeTabClient groupValue;
  final HomeTabClient value;
  final String label;

  @override
  Widget build(BuildContext context) {
    return TextButton(
      style: TextButton.styleFrom(
          foregroundColor: groupValue != value
              ? Colors.black
              : Theme.of(context).colorScheme.secondary,
          ),
      onPressed: () => context.read<HomeCubitClient>().setTab(value),
      child: Text(label),
    );
  }
}

2

Answers


  1. BlocBuilder we know its purpose is to rebuild the widget when the state changes.

    After the Release of Bloc version 6.1.0. We got the access for three different methods.

    context.read<T>()
    context.watch<T>()
    context.select<T>()
    

    Now obviously you can rebuild a widget using BlocConsumer,BlocBuilder
    but let’s say you need to subscribe to many blocs so there came a need for more granular approach like used in your bloc.

    Simply In your case:

    final selectedTab = context.select((HomeCubitClient cubit) => cubit.state.tab);
    

    Is the one responsible for the rebuild of the widget.

    context.select here basically looks for the HomeCubitClient and subscribes to its state. It rebuilds only when the tab variable is changed. The line bellow it subscribes to another bloc and your widget will rebuild when clientId varies inside new state.

    you can achieve similar thing using BlocBuilder and its buildWhen method by nesting two of them which is tedious.

    Login or Signup to reply.
  2. final selectedTab = context.select((HomeCubitClient cubit) => cubit.state.tab);
    

    In this line in build method of HomeViewClient you are listening for HomeCubitClient state updates. So if HomeCubitClient is changed then you active tab is changing correspondingly

    If you check the code of BlocBuilder and its parent BlocBuilderBase you will see that it’s doing literally the same thing (but also overrides didUpdateWidget and didChangeDependencies). So it’s recommended to use BlocBuilder in your case

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search