Flutter State 5 Ways
Tags: fluttercommunity, flutterexamples, flutter
Published: 2020-11-06 05:46:59

---
title: Flutter State 5 Ways
published: true
date: 2020-11-03 15:14:05 UTC
tags: FlutterCommunity,FlutterExamples,flutter
canonical_url: https://poetryincode.dev/flutter-state-5-ways
---

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/8gq3k3wccarbrprkr39t.png)

*To see the code for these examples, click [here](https://github.com/chimon2000/flutter_state_five_ways)*

If you are new to Flutter, or even if you've followed Flutter for a while, you have probably realized that there are many ways to deal with application state.  I have no doubt that there will be a few new entries by the end of the month.  Understanding the differences and trade-offs can be overwhelming since there aren't many examples that offer a direct comparison.  

In my opinion, the best way to learn how to use a library is to build with it.  The best way to compare two libraries is to do the same: build the same feature side-by-side to better understand the tradeoffs.

In this post, I'll walk thru the same application and demonstrate how to implement shared state using the same patterns across 5 different libraries from authors that I am fond of.  These libraries range from popular to obscure and new to old.

1. [Riverpod (with StateNotifier)](#riverpod)
2. [Bloc](#bloc)
3. [flutter_command](#flutter_command)
4. [MobX](#mobx)
5. [binder](#binder)

I will do my best to identify the differences between the libraries and provide an opinion for each approach.  To demonstrate each library's API, we'll implement a Notes app that displays an input field to create new notes and the list of created notes.  You can play with a working demo  [here](https://flutter-state.codemagic.app).

Before we start, I want to clarify that even though I might appear critical of some of these libraries, they still worth using. I find with all of these libraries you can accomplish most of what you need to and my opinion comes with a little subjective bias. I would have not included them otherwise.  Likewise, a library's absence from this article is not an indictment.  My opinions are not omniscient, and even if they were, I am lazy.  Plus, this is a blog post after all, not a book 😊. 

# Getting Started

If you'd like to follow along, create a new Flutter app that to test each approach:

```bash
flutter create state_examples
```

To run the app at any time, execute the `run` command in the project root.

```bash
flutter run
```

There are a few classes that we'll reuse across our examples, so let's define them next.

{% gist  https://gist.github.com/chimon2000/edb85b52005901db927bd0fd96d7db21 %}

We'll also want to refactor our `main.dart` file so that we can easily swap out pages.

{% gist  https://gist.github.com/chimon2000/80204cfea302bd8c4bb343ec96c04b93 %}

# Riverpod

[Riverpod docs](https://riverpod.dev)

Riverpod is a fairly new library created by [Remi Rousselet](https://twitter.com/remi_rousselet) as a direct response to some of the most common issues with his other library [provider](https://pub.dev/packages/provider), specifically the `ProviderNotFound` exception  [raised](https://twitter.com/remi_rousselet/status/1275260772839575554?s=20)  when developers fail to provide a dependency.  In my opinion, that and its simpler API are its two biggest attractions.

When compared to other options, I would say that the mental hurdles are a **slightly lower** if you're just using StateNotifier since you're dealing with a simple API that implements the MVU pattern with tons of documentation.  If you are exercising the full API, then I'd say the hurdle is **much higher** than the field.

## Riverpod in action

To get started with Riverpod, install the library as a dependency:

```yaml
dependencies:
  # ...other dependencies
  flutter_riverpod: ^0.12.1
  riverpod: ^0.12.1
```

Next, add the `ProviderScope` to the root / entry-point of the app:

{% gist  https://gist.github.com/chimon2000/9d321fc35d6f8b629085ea1f6a7abbef %}

Next, to create and mutate state we will create a `NotesController` that extends a `StateNotifier` and a `StateNotifierProvider` to store a reference to `NotesController` and provide it to our application and set some initial state:

{% gist  https://gist.github.com/chimon2000/35bbbae285dc117d2713e578f6f38804 %}

Now we can use the `read` extension method on `BuildContext` and `Consumer` to access the `NotesController` anywhere in the app.  The `read` extension allows us to execute our mutation functions while the `Consumer` widget allows us to subscribe to state changes.  Here is the Notes UI implemented in Riverpod:

{% gist  https://gist.github.com/chimon2000/4b92f854775f1c15f8ba41476e3cd3dd %}

Finally, we'll uncomment `home: SomePage()` and swap out SomePage with the widget we've defined above.

## Verdict

This example may make Riverpod's usage seem trivial, but that is by design.  Riverpod is an extremely powerful library that offers **state management** and **dependency injection**. That is not true for every entry on this list.  But with great power comes great...never mind.  The tradeoff is that power amounts to a [fairly large API](https://pub.dev/documentation/riverpod/latest/riverpod/riverpod-library.html) that might be intimidating.  Riverpod is **fairly well documented**, but you might find yourself bouncing around to different locations depending on what you want to learn.  Do not let that dissuade you from using it since most use cases can be solved just by using State Notifier.

Riverpod is extremely slick, and maybe a bit intimidating but it solves the major problems of provider.  I do not use it currently, but if I started a project already familiar with provider and choosing between the two, I would choose Riverpod in a heartbeat.

# Bloc

[Bloc docs](https://bloclibrary.dev/)

The Bloc library is the [oldest entry](https://verygood.ventures/blog/bloc-from-first-commit) on this list at the grand old age of 2!  Originally created by [Felix Angelov](https://twitter.com/felangelov) as an event-driven take on the Bloc pattern, it was recently re-architected to enable both event-driven and function-driven state updates.  That may sound like a trivial change, but as someone who has worked with event-driven patterns across several frameworks, I can vouch for the efficacy of this change. I have seen the amount of boilerplate and technical debt that is incurred in large event-driven applications.  Being able to choose when to use the pattern matters a lot.

Bloc has two types of state objects: `Blocs`, which are event-driven and inherit from`Cubits`, which are function-driven.  Both inherit from Stream, and shield developers from some of its complexities.  That is essentially where the differences end. Since `Blocs` are an extension of `Cubits`, the rest of the ecosystem (`BlocProvider`, `BlocListener`, `BlocBuilder`, etc.) is shared by both of them.

Bloc also stands apart from every other library on this list as the **gold standard** for documentation.  Its entire API is documented on [bloclibrary.dev](https://bloclibrary.dev), along with examples for every major problem you might want to solve, from using RESTful/GraphQL/Firebase APIs, to handling navigation.  The exceptionalism of their documentation cannot be overstated.

When compared to other options, I would say that the mental hurdles are **lower** since you're dealing with a simple API that implements the MVU pattern with **tons** of documentation.

## Bloc in action

To get started with Bloc, install the library as a dependency:

```yaml
dependencies:
  # ...other dependencies
  bloc: ^6.1.0
  flutter_bloc: ^6.0.6
```

Next, to create and mutate state we will use a `Cubit` from Bloc, initializing our class with some initial state and creating a couple of mutator functions:

{% gist  https://gist.github.com/chimon2000/36296a2833935874e25ba368c68f2388 %}

We will use the `BlocProvider` class to share our `NotesCubit` across the app.  For consistency, we will add `BlocProvider` above `App` in the widget tree.

{% gist  https://gist.github.com/chimon2000/c2c02ceea1622e0219db4896f57d6dd1 %}

Now we can use the `bloc` extension method on `BuildContext` and `BlocBuilder` to access `NotesCubit` in the app.  Here is the Notes UI implemented in Bloc:

{% gist  https://gist.github.com/chimon2000/c1db7acaba9d28c05509d194e2b7d497 %}

Again, we'll uncomment `home: SomePage()` if we haven't already, and swap out SomePage with the widget we've defined above.

## Verdict

I actually work on several projects that have migrated from provider to Bloc. That is not an indictment of Riverpod, because the refactoring is much simpler to Bloc than it is to Riverpod. Also, in cases where we were using Firebase, the fact that we were using Firebase made the refactoring straightforward since both Firebase and Bloc rely on Streams.

Currently, I find myself the **most productive** using Bloc because of its relatively small surface area and how well documented it is.  Again, the care that has been given to making sure I understand how to use every bit of the API **cannot be overstated**.

I won't go as far as saying I'll be using Bloc for the next 5 years, but for me, it's definitely is the **right fit** for right now.

# flutter_command

[flutter_command docs](https://pub.dev/packages/flutter_command)

flutter_command is actually a reimagining of the rx_command library by [Thomas Burkhart](https://twitter.com/ThomasBurkhartB).  The main difference between the two is that the former builds on `ValueNotifier` and `ValueListenableBuilder` while the latter is built on Streams.  Both are derived from .Net's ReactiveCommands, so if you are familiar with that pattern maybe you'll find yourself at home with this library.

When compared to other options, I would say that setup is roughly the same and the mental hurdles are a **bit higher** if you've never worked with ReactiveCommands.

## flutter_command in action

To get started with flutter_command, install the library as a dependency:

```yaml
dependencies:
  # ...other dependencies
  flutter_command: ^0.9.3
```

Next, to create and mutate state we will create a `NotesViewModel` class to define our state as well as the `Command(s)` from flutter_command used to mutate that state:

{% gist  https://gist.github.com/chimon2000/95b8e98274065c11f24e5c2c5bed28ae %}

Now we can use the `NotesViewModel` we created to subscribe to state (using `ValueListenableBuilder`) and execute our `inputChangedCommand` and `updateNotesCommand` to mutate our state.  Here is the Notes UI implemented in **flutter_command**:

{% gist  https://gist.github.com/chimon2000/793a7a813f8afb3ce97d2a3bd33dd8b8 %}

We'll uncomment `home: SomePage()` if we haven't already, and swap out SomePage with the widget we've defined above.

## Verdict

I have very mixed feelings about this library.  For someone familiar with its concepts, it could be a perfect fit.  For someone like me who is coming from the React/Angular community, it never felt like a **natural** fit.  I found the documentation to be adequate for the sake of this exercise.

I would probably not use flutter_command, but I can see how anyone could be just as effective with this library as any other library on this list.  I would definitely recommend it for people already familiar with the patterns or for people who want to experiment with something foreign and unique.

# MobX

[MobX docs](https://mobx.netlify.app/)

MobX.dart has been in the game for a while - almost 2 years!  Anyone with a decent amount of React experience will immediately recognize MobX.dart as a port of MobX.js.  The concepts are the same, minus the fact that you need to use code generation to mirror the magical feats performed under the hood at runtime by a dynamic language like JavaScript.

When compared to other options, I would say that setup is a **bit higher** than others and the mental hurdles are a **bit higher** if you have never worked with observables.

## MobX in Action

To get started with MobX, install the library as a dependency:

```yaml
dependencies:
  # ...other dependencies
  mobx: ^1.2.1+4
  flutter_mobx: ^1.1.0+2

dev_dependencies:
  build_runner: ^1.10.4
  mobx_codegen: ^1.1.1+3
```

Next, to create and mutate state we will use a `Store` from **mobx**, initializing our class with some initial state and creating a couple of mutator functions:

{% gist  https://gist.github.com/chimon2000/d3c06806934a89854b290fac87b4f931 %}

You may immediately notice red squiggles everywhere.  This is because we haven't yet generated the files that our store is dependent upon.   We'll do that by running the following command.

```bash=
flutter packages pub run build_runner build
```

Then we can use the `Observer` from **flutter_mobx** and the actions defined on the store to reference and update the state.  Here is the Notes UI implemented in **mobx**:

{% gist  https://gist.github.com/chimon2000/7982cc4fd86e88cd46328590bc5b26b5 %}

Again, we'll uncomment `home: SomePage()` if we haven't already, and swap out SomePage with the widget we've defined above.

## Verdict

Although I have never used mobx in JavaScript, its concepts were immediately apparent to me since they are essentially the same. I like that it simplifies things even if I find the use of decorators + build generation a bit magical.  I also personally feel that relying on build generation for the state management layer **could be** annoying. After the UI layer, this is the layer that I find myself changing the most.  

The best things that mobx has going for it are its ease of use and great documentation.  It is second only to Bloc on this list in that you should be able to learn everything you need from [mobx.netlify.app](https://mobx.netlify.app/).

# binder

Fresh out of the kitchen, binder was created by [Romain Rastel](https://twitter.com/lets4r). It is heavily inspired by Recoil and Riverpod, seeking to create a library that is easier to learn and has a much smaller API surface area.

When compared to other options, I would say that the mental hurdles are **significantly lower** since you're dealing with a very small API that benefits from ** adequate** documentation.

## binder in Action

[binder docs](https://pub.dev/packages/binder)

To get started with binder, install the library as a dependency:

```yaml
dependencies:
  # ...other dependencies
  binder: ^0.1.5
```

Next, add the BinderScope to the root / entry-point of the app:

{% gist  https://gist.github.com/chimon2000/373545ba33177dfbccb322a751694e98 %}

To create some state we will use a `StateRef` from binder and set some initial state:

{% gist  https://gist.github.com/chimon2000/96975ea3970633801b14e7b7352e51b4 %}

Next, to mutate the state we will create a `Logic` class and a `LogicRef` from binder:

{% gist  https://gist.github.com/chimon2000/62a84c981508a7a01d8716f7eb41ff79 %}

Now we can use the `read`, `use`, and `watch` extension methods on BuildContext to access the StateRef & LogicRef anywhere in the app.  Here is the Notes UI implemented in binder:

{% gist  https://gist.github.com/chimon2000/ad89d1656f4ce8164eafc7f086182a81 %}

Again, we'll uncomment `home: SomePage()` if we haven't already, and swap out SomePage with the widget we've defined above.

## Verdict

binder is **new**.  Like, just-announced-a-week-before-this-post new.  So expecting the same level of documentation as these other libraries would be unfair. For its current state, it is well documented.  Also, because binder borrows heavily from provider and riverpod in an effort to be as close to [Recoil](https://recoiljs.org) as possible, it was extremely easy for me to pick up this library and run.

I have very high hopes for this library and I am looking forward to seeing more examples that highlight its benefits.  If you take nothing else away, binder offers similar benefits to riverpod with a slimmed-down API surface area.

# Conclusion

To be fair to each author, I want to restate that my preferences **are subjective** because they are based on my experience. Also, this is a basic example that doesn't include side-effects/asynchronicity or testing so it doesn't fully exercise the capabilities of these libraries.

Hopefully, this article has provided you with a basic understanding of how to accomplish the same task using each of these libraries and helped you identify their similarities and differences.  Although I have my own preferences, I have no doubt that you can be effective with any entry on this list. 

Prior art:  [React State 5 Ways](https://dev.to/dabit3/react-state-6-ways-2bem)