Create a simple Flutter app with Riverpod v1.0.0
Tags: flutter, tutorial, beginners
Published: 2021-11-14 07:54:08

# Riverpod

Riverpod is a Reactive State-Management and Dependency Injection Framework library on Flutter. Nov 5, 2021, the release date of version 1.0.0 has come, and modified some features. In this article, I'll try to describe how you would manage the state by Riverpod with simple application.

# What is Riverpod?

- No more `ProviderNotFoundException`
- Provider inspires Riverpod but solves some of its key issues
- No dependency on Flutter

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

# Goal

Let's make a simple app that counts number per pushing a button.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6dqznc04uh49k8t24ovj.png)

# Environment

```yaml
dependencies:
  flutter:
    sdk: flutter
  riverpod: ^1.0.0
  flutter_hooks: ^0.18.0
  hooks_riverpod: ^1.0.0
```

# 1. Update state with StateNotifierProvider

Use `StateNotifierProvider` , `StateNotifier` , `HookConsumerWidget` to update and read state.

# 2. Import packages

```dart
import 'package:flutter/material.dart';
import 'package:riverpod/riverpod.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
```

# 3.  Define countStateProvider variable with StateNotifierProvider

`StateNotifierProvider` is combined with `StateNotifier` .

[StateNotifierProvider class - riverpod library - Dart API](https://pub.dev/documentation/riverpod/latest/riverpod/StateNotifierProvider-class.html)

```dart
final countStateProvider =
    StateNotifierProvider<CountState, int>((ref) => CountState(0));
```

# 4. Set up CountState class with StateNotifier

`StateNotifier` is an observable class that stores a single immutable [state](https://pub-dev.translate.goog/documentation/state_notifier/latest/state_notifier/StateNotifier/state.html?_x_tr_sl=auto&_x_tr_tl=ja&_x_tr_hl=ja&_x_tr_pto=nui,op). At first, create CountState class extended StateNotifier class.

```dart
class CountState extends StateNotifier<int> {
  CountState(int count) : super(count);

  void increment() => state = state + 1;
}
```

StateNotifier is designed to be subclassed. You first need to give an initial value to the super constructor. In the above, CountState class receives the count argument, and then passes it to the super constructor.

```dart
CountState(int count) : super(count);
```

The next shows the published method to allow other objects modify to modify the counter.

```dart
void increment() => state = state + 1;
```

It is possible to define multiple methods in StateNotifier class.

```dart
void increment() => state++;
void decrement() => state--;
```

# 5. ProviderScope on Riverpod

All applications dealing with Riverpod must contain a ProviderScope at the root of your widget tree. Thus, let's wrap MyApp class defined next chapter by ProviderScope.

```dart
void main() {
  runApp(ProviderScope(
    child: MyApp(),
  ));
}
```

# 6. MyAPP with HookConsumerWidget

Let's make a MaterialApp in MyApp class extending HookConsumerWidget, the alternative of HookWidget, released after version 1.0.0.

```dart
class MyApp extends HookConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final int count = ref.watch(countStateProvider);

    return MaterialApp(
      home: Scaffold(
        body: Center(child: Text('$count')),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            ref.read(countStateProvider.notifier).increment();
          },
        ),
      ),
    );
  }
}
```

To watch the state in countStateProvider, define the count variable with ref.watch(), replaced from useProvider on the previous version.

```dart
Widget build(BuildContext context, WidgetRef ref) {
  final int count = ref.watch(countStateProvider);
```

Add ref.read() to call increment() function in CountState for when pressing floatingActionButton.

```dart
onPressed: () {
  ref.read(countStateProvider.notifier).increment();
},
```

# 7. Whole code

```dart
import 'package:flutter/material.dart';
import 'package:riverpod/riverpod.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

final countStateProvider =
    StateNotifierProvider<CountState, int>((ref) => CountState(0));

class CountState extends StateNotifier<int> {
  CountState(int count) : super(count);

  void increment() => state = state + 1;
}

void main() {
  runApp(ProviderScope(
    child: MyApp(),
  ));
}

class MyApp extends HookConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final int count = ref.watch(countStateProvider);

    return MaterialApp(
      home: Scaffold(
        body: Center(child: Text('$count')),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            ref.read(countStateProvider.notifier).increment();
          },
        ),
      ),
    );
  }
}
```