Flutter Riverpod Example – Category Selection
Tags: flutter
Published: 2021-01-14 19:16:35

---
title: Flutter Riverpod Example – Category Selection
published: true
date: 2021-01-14 19:10:37 UTC
tags: Flutter
canonical_url: https://bartvwezel.nl/flutter/flutter-riverpod-example-category-selection/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/e8qmt4cgtgmxpoh2xt1l.jpg
---

In the latest blog posts, I have been writing about Flutter Hooks and the Provider to simplify state management in Flutter. We described how to simplify the modal dialog selector of categories with [Flutter Hooks](https://bartvwezel.nl/flutter/flutter-hooks-usestate-example/) and with the [Provider](https://bartvwezel.nl/flutter/flutter-provider-example-category-selector/). However, there is also an option to combine both. [Riverpod](https://riverpod.dev/) is a Provider but different! Riverpod has multiple benefits such a support for multiple providers of the same type, combining asynchronous providers, and adding providers from anywhere. Furthermore, it provides a way to combine the Provider with Hooks! In this blog post, we will show an example showing how to use Flutter Riverpod.

## Riverpod different packages

Riverpod provides multiple packages to use state management.

| App type | Package name | Description |
| --- | --- | --- |
| Flutter + [flutter\_hooks](https://github.com/rrousselGit/flutter_hooks) | [hooks\_riverpod](https://pub.dev/packages/hooks_riverpod) | A way to use both [flutter\_hooks](https://github.com/rrousselGit/flutter_hooks) and [Riverpod](https://github.com/rrousselgit/river_pod) together, while offering small extras. |
| Flutter only | [flutter\_riverpod](https://pub.dev/packages/flutter_riverpod) | A basic way of using [Riverpod](https://github.com/rrousselgit/river_pod), which does not depend on [flutter\_hooks](https://github.com/rrousselGit/flutter_hooks). |
| Dart only (No Flutter) | [riverpod](https://github.com/rrousselGit/river_pod/tree/master/packages/riverpod) | A version of [Riverpod](https://github.com/rrousselgit/river_pod) with all the classes related to Flutter stripped out. |

<figcaption>Table describing the different packages from the <a href="https://riverpod.dev/docs/getting_started">documentation</a>!</figcaption>

They have even included an image to make it even more simple!

[![](https://bartvwezel.nl/wp-content/uploads/2021/01/package_decision_graph-782c08f2546d43a4bdddf91fb5217246.svg)](https://riverpod.dev/docs/getting_started)<figcaption>Image describing when to use which package from the getting started documents of <a href="https://riverpod.dev/docs/getting_started">Riverpod</a></figcaption>

Since we are using Flutter we are interested in both hooks\_riverpod and flutter\_riverpod. We will first provide an example with flutter\_riverpod and then rewrite the same use case with hooks\_riverpod to show the differences!

## Example with Flutter Riverpod

Before we can start with coding, we are going to add a dependency to the project.

```YAML
dependencies:
  flutter_riverpod: ^0.12.1
```

Do not forget to install the dependency, running the following command:

```
flutter pub get
```

That is it! We can now start with the example. The example we are going to build is a list of categories that are selectable. Underneath the checkboxes is a list that displays the currently selected values. This means that two Widgets need access to the list of categories and to the currently selected values.

For this, we are going to introduce a **StateNotifier**. The **StateNotifier** is of a type. We are going to maintain a map of String to Booleans. In our case, the Strings are the categories and the boolean maintains whether the value is selected or not. We are going to introduce a toggle method that will toggle the selected value of a category. We are going to trigger the updates by setting state = state.

```dart
class CategoryList extends StateNotifier> {
  CategoryList(Map state) : super(state);

  void toggle(String item) {
    state[item] = !state[item];
    state = state;
  }
}
```

We can use this StateNotifier, to create a **StateNotifierProvider**. For this, we created a helper method that converts a list of Strings into the initial state of the **StateNotifier**.

```dart
final categoryListProvider =StateNotifierProvider((_) => createCategoryList(["Banana", "Pear", "Apple", "Strawberry", "Pineapple"]));

CategoryList createCategoryList(List values) {
  final Map categories = Map();
  values.forEach((value) {
    categories.putIfAbsent(value, () => false);
  });
  return CategoryList(categories);
}
```

We can use **StateNotifierProvider** to create two different providers. One for the list of all categories, another one for the list of currently selected values. We can create a list with a **Provider** and access the state of the **CategoryList** through the **categoryListProvider**.

```dart
final selectedCategories = Provider((ref) => ref
    .watch(categoryListProvider.state)
    .entries
    .where((category) => category.value)
    .map((e) => e.key)
    .toList());

final allCategories = Provider((ref) => ref.watch(categoryListProvider.state).keys.toList());
```

We now have the state we need for the Widgets, so let’s get started! We are going to create a new Widget that extends the **ConsumerWidget**. In the ConsumerWidget we have to override a different build function as a normal Widget. The method provides a watch function that we can use to access the provider we created. With _**watch(selectedCategories**_) we can access the list of select categories. Then with the ListView we will display the selected values.

```dart
class SelectedCategories extends ConsumerWidget {
  @override
  Widget build(BuildContext context,
      T Function(ProviderBase provider) watch) {
    final categoryList = watch(selectedCategories);

    return Flexible(
      child: ListView.builder(
          itemCount: categoryList.length,
          itemBuilder: (BuildContext context, int index) {
            return Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text(categoryList[index]),
            );
          }),
    );
  }
}
```

We can now show the selected categories, but we have no way yet to select the categories. We again have to convert the Widget into a **ConsumerWidget**. Here we are going to access both the list of all categories as the selected list. This is done in the same way as in the **SelectedCategories** Widget. What we are interested in now is in selecting the categories. Through the context, we can access the CategoryList and toggle the category with the toggle function: **_context.read(categoryListProvider).toggle(categoryList[index]);_**

```dart
class CategoryFilter extends ConsumerWidget {
  @override
  Widget build(BuildContext context,
      T Function(ProviderBase provider) watch) {
    final selectedCategoryList = watch(selectedCategories);
    final categoryList = watch(allCategories);

    return Flexible(
      child: ListView.builder(
          itemCount: categoryList.length,
          itemBuilder: (BuildContext context, int index) {
            return CheckboxListTile(
              value: selectedCategoryList.contains(categoryList[index]),
              onChanged: (bool selected) {
                context.read(categoryListProvider).toggle(categoryList[index]);
              },
              title: Text(categoryList[index]),
            );
          }),
    );
  }
}
```

That is all we need to do! If you are interested in the code so far, that is available here on [Github](https://github.com/Barttje/riverpod_selection_example). In the next part, we are going to introduce Riverpod hooks!

## Example with Riverpod Hooks

For the second example, we have to adjust our dependencies. We are going to add the dependency for Hooks Riverpod. Furthermore, we need to add the dependency on Flutter Hooks itself.

```YAML
dependencies:
  flutter_hooks: ^0.15.0
  hooks_riverpod: ^0.12.1
```

There are only a few things we have to rewrite the previous example with hooks. We can change the ConsumerWidgets into HookWidgets, which allows us to make use of hooks. We no longer have access to the watch function provided by the ConsumerWidget. This means we have to access the list in another way. For this, we can use the hook provided by Hooks Riverpod: **useProvider**.

```dart
class SelectedCategories extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final categoryList = useProvider(selectedCategories);
    return Flexible(
      child: ListView.builder(
          itemCount: categoryList.length,
          itemBuilder: (BuildContext context, int index) {
            return Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text(categoryList[index]),
            );
          }),
    );
  }
}
```

We can repeat the same trick for the other widget. We convert it to a HookWidget and use the **useProvider** hook to access both the complete list, as the selected list. Since we still have access to the build context we can toggle the values of the list in

```dart
class CategoryFilter extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final selectedCategoryList = useProvider(selectedCategories);
    final categoryList = useProvider(allCategories);

    return Flexible(
      child: ListView.builder(
          itemCount: categoryList.length,
          itemBuilder: (BuildContext context, int index) {
            return CheckboxListTile(
              value: selectedCategoryList.contains(categoryList[index]),
              onChanged: (bool selected) {
                context.read(categoryListProvider).toggle(categoryList[index]);
              },
              title: Text(categoryList[index]),
            );
          }),
    );
  }
}
```

With the StateNotifier we can keep the state in one place. Another benefit is that we can create multiple providers of the StateNotifier. Now can easily keep the full list and the selected list available. The full code can be found on [Github](https://github.com/Barttje/riverpod_selection_example). If you have any questions, feel free to ask them in the comments!

The post [Flutter Riverpod Example – Category Selection](https://bartvwezel.nl/flutter/flutter-riverpod-example-category-selection/) appeared first on [Barttje](https://bartvwezel.nl).