# `bloc`

| Package | Kind | Provides the role | Needs | Choose with |
| --- | --- | --- | --- | --- |
| [`smf_bloc`](https://pub.dev/packages/smf_bloc) | infrastructure | State management | nothing | `-m bloc` |

`bloc` manages the state of screens with [BLoC](https://bloclibrary.dev), through [flutter_bloc](https://pub.dev/packages/flutter_bloc) 9.

## What it adds to the app

The module adds `flutter_bloc: ^9.1.1` to the dependencies and no code, since BLoC needs neither a widget around the app nor start-up code.

In the [guide for coding agents](https://doc.saymyframe.com/guides/coding-agents.md) of the app, the module writes the section "State management". The state of a screen is a `Cubit` in the directory of its feature. The screen provides it with a `BlocProvider` and passes the state on to a view that imports no `flutter_bloc`. State that several screens read gets a `BlocProvider` around the root widget in `lib/main.dart`. After an `await`, a `Cubit` checks `isClosed` before it calls `emit()`. And a widget talks only to a `Cubit`, never to a service or a DI container.

## Features with state

A feature that keeps state supports BLoC through a variant keyed by the id of this module, `bloc`. The variant brings the Cubits or Blocs of the feature's screens and provides them where the screens need them. Usually the feature's composition file creates them, with the services they need. The variant depends on `flutter_bloc` with the constraint `any`, so the version comes from this module. See [Write a feature module](https://doc.saymyframe.com/extending/feature-module.md).

Among the built-in features, [`sign_in`](https://doc.saymyframe.com/modules/sign-in.md) has such a variant:

- Each of its screens has a cubit in a file next to it, such as `SignInCubit` in `lib/features/sign_in/sign_in_cubit.dart`. The screen provides its cubit with a `BlocProvider` and builds its view from the state with a `BlocBuilder`. The view is a plain Flutter widget that imports nothing of `flutter_bloc`.
- `lib/features/sign_in/sign_in_composition.dart` creates the cubits. A cubit takes what it needs through its constructor, here the session of the app, so a test creates one with a session of its own.
- State that several screens read has its `BlocProvider` around the root widget, in `runApp()`. The module puts its `SessionCubit` there, and a widget reads who uses the app with `context.watch<SessionCubit>().state`.
- A cubit checks `isClosed` after an `await`, since the user may have left the screen while the call was on its way.

`home`, `onboarding` and `settings` keep no state in a state manager, so they work the same with `bloc` and without it.

## Choosing it

`smf create` asks which module manages the state of the app, and offers [`riverpod`](https://doc.saymyframe.com/modules/riverpod.md) and None as well. To choose it without the question:

```bash
smf create my_app -m bloc
```

An app has at most one module that manages its state.
