# Why We Use flutter_bloc for State Management

> An in-depth look at the benefits flutter_bloc brings our team at VGV

- Source: https://verygood.ventures/blog/why-we-use-flutter-bloc/
- Published: 2021-06-23
- Author: Jorge Coca
- Tags: Architecture, Best Practices, Open Source

---

State management is the debate that just won’t go away. It seems like every week, there is a new discussion attempting to determine which pattern or library is the best approach for state management in Flutter. We get it — selecting a state management solution could determine your entire application architecture, which is no small decision. And, there are many [popular state management solutions](https://flutter.dev/docs/development/data-and-backend/state-mgmt/options) to choose from such as [**redux**](https://pub.dev/packages/redux), [**mobX**](https://pub.dev/packages/mobx), [**flutter_bloc**](https://pub.dev/packages/flutter_bloc), and even vanilla [**setState**](https://api.flutter.dev/flutter/widgets/State/setState.html). 

**Our perspective on the state management debate is: *The best state management solution is the one that works the best for you.*** **When it comes to our projects at VGV, we know exactly what state management solution works best for our team:** [**flutter_bloc**](https://bloclibrary.dev/#/)**.** 

This blog is not intended to be the last word in conversations about state management, nor is it an attempt to prove that there is a “winner” once and for all. Instead, we will explain why we use **flutter\_bloc**, the benefits it brings to our team, and how we address common concerns about it. 

## Building Expertise on a Solid Foundation

We work with clients across various industries — including automotive, entertainment, healthcare, and financial services. To date, we’ve provided Flutter expertise to over 20 companies, which means we’ve seen a lot of Flutter apps, as well as a mix of approaches to scalable Flutter development. Our team continually pools together our knowledge and refines the way we approach building scalable apps — that is, apps optimized for growth over the long run ([read what we mean by scalable here](https://verygood.ventures/blog/scalable-best-practices/)). 

Building a robust product requires our team to pick and define a set of tools and practices that makes us feel comfortable and confident in our ability to deliver and maintain that product successfully over time. One of those tools you need first is *your state management solution.*

A while ago we had to ask ourselves as a team: *How do we provide more value to our customers?* We had two options:

-   Learn and continually improve on a single, well-known and popular solution
-   Start each project with a different solution, hoping for the benefits and accepting risks it might bring 

### At Very Good Ventures, we are in the business of providing confidence to our clients: we deliver our best when we avoid surprises and are predictable and [**boring**](https://verygood.ventures/blog/boring-code-part-1/).

We came to the conclusion that it would be easier and more impactful in the long-run to commit to a single tool that we have used before and know works well, rather than spending our time testing out other solutions. The tool we have selected is **flutter\_bloc**. Before we explain the specific benefits that it brings to our team, we should note that some of our clients come to us with codebases that are already using a state management solution other than **flutter\_bloc**.

In these cases, we will work with them to deliver the best code with their preferred tools. However, our job as consultants also entails that we provide recommendations, especially when clients are looking for a solid architecture to start building from, or an effective way to refactor existing code. In these cases, we recommend **flutter\_bloc** as our preferred solution for building predictable, scalable Flutter applications. 

## Predictable, simple, and highly testable

One of the cultural values we have defined at Very Good Ventures is to **“scale with standards.”**  We define it like this:

-   We create scale through solid, repeatable practices
-   We grow client capabilities in addition to creating software
-   We are principled with our work and avoid shortcuts
-   We seek out and build solutions to repeating needs
-   We embrace automation and long-run optimizations

Once our team defined a set of values and principles that we wanted to follow, it was much easier to pick the tool that most accurately represents and embraces those values. And, well, **flutter\_bloc** is the perfect match for this: 

![Screenshot of bloclibrary.dev website](/assets/images/blog/why-we-use-flutter-bloc/body-0.jpeg)
*bloclibrary.dev*

### Predictable

One of the biggest challenges of product development is knowing, at any point in time, the real state of your application.

Flutter helps developers to answer this question through the [widget tree](https://flutter.dev/docs/development/ui/layout). But in order to make your product interesting and interactive, you will need to modify the widget tree; that is, you need to decide how you will manage the structure of your tree (or, in other words, state management).

**flutter\_bloc** allows you to decompose your app’s state into smaller, well-defined state machines that transform events into zero, one, or multiple states. For example, when you open your favorite food delivery app, something like this might happen:

*When I open my favorite food delivery app, I get a loading indicator that indicates that we are fetching data from the network. If the connection was successful, I will be presented with a list of my favorite restaurants. Otherwise, an error message will be displayed.*

Say no more! You could code that requirement in a predictable way using an approximation of plain English:

```dart
@override
Stream<FavoriteRestaurantState> mapEventsToState(FavoriteRestaurantEvent event) async* {
  if (event is AppOpened) {
    yield FavoriteRestaurantsLoadInProgress();
    try {
      final restaurants = await restaurantsRepository.fetchFavoriteRestaurants();
      yield FavoriteRestaurantsSuccess(restaurants);
    } catch (_) {
      yield FavoriteRestaurantsFailure();
    }
  }
}
```

### Simple

Every UI application is reactive by nature: your UI is idle most of the time waiting for your customer’s interaction (or a system event) to then provide and transform data. But *you never know* when that interaction will happen, or even if it will happen at all. That’s why your application needs to *react* to those events. 

Traditionally, the APIs that helped developers to capture that *reactiveness* were powerful, but incredibly complex to use properly (callbacks, Rx, Streams, etc.).

With **flutter\_bloc**, we still honor the fact that every application is reactive by nature, while abstracting the complexity of streams from developers. Forget about maintaining complex subscriptions and lifecycles, and instead, focus on the real, predictable interactions of your product. Only focus on what matters: for the received event, the state that we need produced. 

### Highly testable

One of the key qualities that VGV developers have to feel confident about when selecting tools is that they should be testable. Along with the production code, our team [values automated tests](https://verygood.ventures/blog/guide-to-flutter-testing/) that can validate the behavior of the product  at any point in time.

[**bloc_test**](https://pub.dev/packages/bloc_test) is a utility library that removes all the complexity of testing reactive code, and allows you to unit test your code with almost no setup required.

```dart
blocTest(
  'emits [1] when CounterEvent.increment is added',
  build: () => counterBloc,
  act: (bloc) => bloc.add(CounterEvent.increment),
  expect: () => [1],
);

blocTest(
  'emits [-1] when CounterEvent.decrement is added',
  build: () => counterBloc,
  act: (bloc) => bloc.add(CounterEvent.decrement),
  expect: () => [-1],
);
```

### Onboarding and documentation

Documentation, tutorials, examples, guides, and migration guides are all key to ensure a healthy and productive community. **flutter\_bloc** is known in the community for its [detailed documentation](https://bloclibrary.dev/#/gettingstarted) (which currently provides translations for 10 languages), selection of [high-quality tutorials](https://bloclibrary.dev/#/fluttercountertutorial) (from a simple counter project to complex integrations with Firebase), as well as support for [Angular Dart](https://pub.dev/packages/angular_bloc).

We’ve been able to successfully onboard entire engineering organizations by just going through the **flutter\_bloc** documentation. Even our internal onboarding, especially these days when remote work is the norm, heavily relies on the **flutter\_bloc** documentation. 

### Used by thousands

**flutter\_bloc** started as a solution for an internal need that some of our teammates faced when working at BMW: *how can we help our teammates all around the world commit their features to Flutter in an efficient, productive, and safe way?* **flutter\_bloc** quickly scaled from being used internally by a few dozen engineers to being open-sourced with more than 7,000 stars on Github! To put it in perspective, [dagger](https://github.com/square/dagger) has 7,300 stars on GitHub. That’s a huge accomplishment for a Flutter package!

In addition, **flutter\_bloc** has helped companies of all sizes to scale and release their products successfully, and we are incredibly proud and excited to keep investing and supporting this amazing library! **flutter\_bloc** has even been named a [Flutter Favorite](https://flutter.dev/docs/development/packages-and-plugins/favorites) by the Flutter Ecosystem Committee, who consider metrics like overall package score, feature completeness, usability, and more. 

## Addressing some bloc concerns

### *“Bloc is too complex.”*

A quote that is very present in our work is [**“complex problems, easy solutions.”**](https://speakerdeck.com/jorgecoca/flutter-at-scale?slide=4) Flutter already introduces a very powerful solution to manage state: **setState** on **StatefulWidgets***.* So, why do we need a state management solution at all?

**setState** is ultimately what every state management solution ends up calling to modify the widget tree, but it can be easy to mismanage when your application gets complex, especially when it comes to managing multiple variables, touch events, navigation, push notifications, analytics. At scale, problems can arise, such as passing state around the widget tree ([prop-drilling](https://kentcdodds.com/blog/prop-drilling)), unnecessary widget tree rebuilds, and code that is generally hard to read and test due to logic injected throughout the UI.

With **flutter\_bloc**, we introduce a way to adapt to the reactive nature of every application without having to be proficient in tools and APIs like [**Streams**](https://dart.dev/tutorials/language/streams) or [**RxDart**](https://pub.dev/packages/rxdart)*.* You will still need to learn a few [core concepts](https://bloclibrary.dev/#/coreconcepts) such as the **Bloc API** itself and the difference between a **BlocBuilder** and a **BlocListener**. The good news is these are all things that are [well-documented](https://bloclibrary.dev/#/gettingstarted) and covered in [multiple](https://bloclibrary.dev/#/fluttercountertutorial) [tutorials](https://bloclibrary.dev/#/flutterweathertutorial).

**flutter\_bloc** might not be the first tool you need to learn when getting started in programming, or even during your first attempts with Flutter (after all, you need to learn first how to walk before you can run). But in our experience, **flutter\_bloc** can boost your productivity and efficiency as a developer due to its simplicity and relatively few concepts to learn.

### *“Bloc has too much boilerplate.”* 

**flutter\_bloc** requires you to model your events and states with different classes. This, compared to the simplicity of simply declaring variables if you were using **setState***,* could be considered a step back since it might require you to write more lines of code to achieve the same functionality. However, is the sheer number of lines of code a fitting metric for considering a piece of software *good software?*

A beautiful thing about modeling your events and states with separate classes is that:

-   You can truly make them immutable
-   Your events, states, and their properties are completely independent of each other

If your problem is complex, what at the beginning might seem like a burden (*“Ugh, do I have to write a single class per state?”*) will turn into a benefit! (*“Yes! I am so glad that my success logic is completely separate from my error handling!”*).

Alternatively, if you truly consider your event information boilerplate, you can default to using [**cubit**](https://bloclibrary.dev/#/coreconcepts?id=cubit) instead of **bloc**: after all, **cubit** is mostly a bloc without events as a class, but as a public method. You'll lose functionality, like automating logs and analytic events, but you can then write less code without sacrificing legibility. Tooling can also make it easier to write this code quickly and consistently — such as the bloc [VS Code](https://marketplace.visualstudio.com/items?itemName=FelixAngelov.bloc) and [IntelliJ](https://plugins.jetbrains.com/plugin/12129-bloc) extensions. 

Finally, we are excited and hopeful for the changes that the Dart team is considering with the [**static metaprogramming**](https://github.com/dart-lang/language/issues/1482) issue; they could help even further to simplify the **bloc API**, be more strict and safe, and do *more with less.*

## We have the highest level of confidence in flutter\_bloc

In our business, providing confidence and meeting expectations is key, which means our team must be flexible and adapt to changing client needs. As a highly experienced team of Flutter developers, clients ask us to recommend tools and approaches that will provide the best results. When it comes to state management, **flutter\_bloc** is the fastest and safest path to engineering excellence for our team. 


*Scarlett Wardrop contributed to this article.*
