Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migration page from "old" notifiers to "new" notifiers #2793

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
135cb94
Some TODOs
lucavenir Aug 4, 2023
55fdf73
Cross referenced this page in the "from provider" migration pages
lucavenir Aug 4, 2023
664f92f
An introduction
lucavenir Aug 4, 2023
2fbe2c6
From StateNotifier to Notifier intro
lucavenir Aug 4, 2023
bef8790
Initialization with Notifier vs with StateNotifier
lucavenir Aug 4, 2023
a41579c
No `ref` pipe down is ever needed
lucavenir Aug 4, 2023
6598633
Renamed some files
lucavenir Aug 4, 2023
5f91c94
Migrating from `StateProvider`
lucavenir Aug 4, 2023
4e5162c
Changing titles
lucavenir Aug 4, 2023
55ab65d
A different dispose lifecycle
lucavenir Aug 4, 2023
c60fd19
Improved the "ref" paragraph
lucavenir Aug 4, 2023
3578b8a
Specified how the new APIs are bound to .family and .autoDispose
lucavenir Aug 4, 2023
2b10450
Another quick review
lucavenir Aug 4, 2023
7409023
Post-initialization effects mentioned
lucavenir Aug 4, 2023
368423c
Added some TODOs
lucavenir Aug 4, 2023
c8f43b0
from `.addListener` to `.listen`
lucavenir Aug 5, 2023
9fba2e2
Renamed examples and fixed comptime errors
lucavenir Aug 5, 2023
d88732e
from `debugState` to `container.read` for testing purposes
lucavenir Aug 5, 2023
e1aa350
Fixed pipeline (hopefully)
lucavenir Aug 5, 2023
64bbbb2
Fixed "state provider" code block
lucavenir Aug 5, 2023
c37d087
Renamed some paragraphs
lucavenir Aug 5, 2023
f6d9106
A clearer link reference
lucavenir Aug 22, 2023
6815e66
Used inline links where necessary
lucavenir Aug 22, 2023
e805e9f
No more "from 1.0 to 2.0".
lucavenir Aug 22, 2023
616bd2c
Changed intro: why Notifiers are cool
lucavenir Aug 22, 2023
d53438c
Changed title
lucavenir Aug 22, 2023
447707f
Removed useless statement
lucavenir Aug 22, 2023
0429497
Post-init effects are now more explicit
lucavenir Aug 22, 2023
5b1a86f
Re-arranged the introduction, completely
lucavenir Aug 22, 2023
904367d
Removed redundant docs about `ref` being available on Notifier
lucavenir Aug 22, 2023
4f249c4
Improved section about .family and .autoDispose
lucavenir Aug 22, 2023
a00e7bc
Re-organized this page with "other differences"
lucavenir Aug 23, 2023
b1d140f
Migrating to AsyncNotifier
lucavenir Aug 24, 2023
eba9923
Removed ambiguous statement
lucavenir Aug 24, 2023
7f7e1c5
Improved the .autoDispose and .family section
lucavenir Aug 24, 2023
e2f74ed
Re-structured the remaining parts of the page
lucavenir Aug 24, 2023
befd509
Re-written the lifecycle paragraph
lucavenir Aug 24, 2023
aa8ce3d
Again, re-structured the flow of the document
lucavenir Aug 24, 2023
3b2a750
Tried to format the document
lucavenir Aug 24, 2023
09b16e5
Improved the "other stuff" paragraph and subparagraphs
lucavenir Aug 24, 2023
98cca35
Added a migration example for `ChangeNotifier`
lucavenir Aug 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions website/docs/from_provider/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,21 @@ final myNotifierProvider = ChangeNotifierProvider<MyNotifier>((ref) {
});
```

As you can see Riverpod exposes a [ChangeNotifierProvider] class,
As you can see, Riverpod exposes a [ChangeNotifierProvider] class,
which is there precisely to support migrations from pkg:Provider.

Keep in mind that this provider is not recommended when writing new code,
and it is not the best way to use Riverpod, but it's a gentle and very easy way to start your migration.

:::tip
There is no rush to *immediately* try to change your `ChangeNotifier`s into the more modern [Riverpod's providers].
Some requite a bit of a paradigm shift, so it may be difficult to do initially.
Some requite a bit of [work], so it may be difficult to do in one take.

Take your time, as it is important to get yourself familiar with Riverpod first;
you'll quickly find out that *almost* all Providers from pkg:provider have a strict equivalent in pkg:riverpod.
:::


## Starts with *leaves*

Start with Providers that do not depend on anything else, i.e. start with the *leaves* in your dependency tree.
Expand Down Expand Up @@ -120,6 +121,10 @@ final myNotifierProvider = NotifierProvider<MyNotifier, int>(MyNotifier.new);

This operation might take some time and might lead to some errors, so don't rush doing this all at once.

Please follow [this migration guide] to migrate from `ChangeNotifier` to the more modern
`Notifier` and `AsyncNotifier`, one step at a time.


## Migrating `ProxyProvider`s
Within pkg:Provider, `ProxyProvider` is used to combine values from other Providers;
its build depends on the value of other providers, reactively.
Expand Down Expand Up @@ -204,4 +209,6 @@ Following this guide, you *can* migrate towards codegen as a further step forwar
[are composable by default]: /docs/from_provider/motivation#combining-providers-is-hard-and-error-prone
[as mentioned above]: /docs/from_provider/quickstart#start-with-changenotifierprovider
[Riverpod's `Consumer` APIs]: /docs/concepts/reading
[lazy by default]: /docs/concepts/provider_lifecycles
[lazy by default]: /docs/concepts/provider_lifecycles
[work]: /docs/from_provider/quickstart#migrate-one-provider-at-a-time
[this migration guide]: /docs/migration/1.0.0_to_2.0.0#migrating-from-statenotifier
16 changes: 16 additions & 0 deletions website/docs/migration/add_listener/add_listener.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// ignore_for_file: avoid_print

import 'package:flutter/material.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'add_listener.g.dart';

/* SNIPPET START */
@riverpod
class MyNotifier extends _$MyNotifier {
@override
int build() {
ref.listenSelf((_, next) => debugPrint('$next'));
lucavenir marked this conversation as resolved.
Show resolved Hide resolved
return 0;
}
}
27 changes: 27 additions & 0 deletions website/docs/migration/add_listener/add_listener.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions website/docs/migration/add_listener/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import raw from "!!raw-loader!./raw.dart";
import codegen from "!!raw-loader!./add_listener.dart";

export default {
raw,
hooks: raw,
codegen,
hooksCodegen: codegen,
};
15 changes: 15 additions & 0 deletions website/docs/migration/add_listener/raw.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// ignore_for_file: avoid_print

import 'package:flutter/material.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

/* SNIPPET START */
class MyNotifier extends Notifier<int> {
@override
int build() {
ref.listenSelf((_, next) => debugPrint('$next'));
return 0;
}
}

final myNotifierProvider = NotifierProvider<MyNotifier, int>(MyNotifier.new);
19 changes: 19 additions & 0 deletions website/docs/migration/async_notifier/async_notifier.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// ignore_for_file: avoid_print

import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'async_notifier.g.dart';

class Todo {}

/* SNIPPET START */
@riverpod
class AsyncTodosNotifier extends _$AsyncTodosNotifier {
@override
FutureOr<List<Todo>> build() {
// mock of a network request
return Future.delayed(const Duration(seconds: 1), () => []);
lucavenir marked this conversation as resolved.
Show resolved Hide resolved
}

// ...
}
29 changes: 29 additions & 0 deletions website/docs/migration/async_notifier/async_notifier.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions website/docs/migration/async_notifier/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import raw from "!!raw-loader!./raw.dart";
import codegen from "!!raw-loader!./async_notifier.dart";

export default {
raw,
hooks: raw,
codegen,
hooksCodegen: codegen,
};
20 changes: 20 additions & 0 deletions website/docs/migration/async_notifier/raw.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ignore_for_file: avoid_print

import 'package:riverpod_annotation/riverpod_annotation.dart';

class Todo {}

/* SNIPPET START */
class AsyncTodosNotifier extends AsyncNotifier<List<Todo>> {
@override
FutureOr<List<Todo>> build() {
// mock of a network request
return Future.delayed(const Duration(seconds: 1), () => []);
}

// ...
}

final asyncTodosNotifier = AsyncNotifierProvider<AsyncTodosNotifier, List<Todo>>(
AsyncTodosNotifier.new,
);
21 changes: 21 additions & 0 deletions website/docs/migration/build_init/build_init.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// ignore_for_file: avoid_print

import 'dart:math';

import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../utils.dart';

part 'build_init.g.dart';

/* SNIPPET START */
@riverpod
class WellNotifier extends _$WellNotifier {
@override
int build() {
final availableToDrink = ref.watch(availableWater);
return availableToDrink;
}

void drink(int liters) => state = min(state - liters, 0);
}
27 changes: 27 additions & 0 deletions website/docs/migration/build_init/build_init.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions website/docs/migration/build_init/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import raw from "!!raw-loader!./raw.dart";
import codegen from "!!raw-loader!./build_init.dart";

export default {
raw,
hooks: raw,
codegen,
hooksCodegen: codegen,
};
21 changes: 21 additions & 0 deletions website/docs/migration/build_init/raw.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// ignore_for_file: avoid_print

import 'dart:math';

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../utils.dart';

/* SNIPPET START */
class WellNotifier extends Notifier<int> {
@override
int build() {
final availableToDrink = ref.watch(availableWater);
return availableToDrink;
}

void drink(int liters) => state = min(state - liters, 0);
}

final wellNotifierProvider = NotifierProvider<WellNotifier, int>(WellNotifier.new);
26 changes: 26 additions & 0 deletions website/docs/migration/family_and_dispose/family_and_dispose.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'dart:math';

import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../utils.dart';

part 'family_and_dispose.g.dart';

/* SNIPPET START */
@riverpod
class BugsEncounteredNotifier extends _$BugsEncounteredNotifier {
late String _id;
@override
FutureOr<int> build(String featureId) {
_id = featureId;
lucavenir marked this conversation as resolved.
Show resolved Hide resolved
return 99;
}

Future<void> fix(int amount) async {
state = await AsyncValue.guard(() async {
lucavenir marked this conversation as resolved.
Show resolved Hide resolved
final old = state.requireValue;
final result = await ref.read(taskTrackerProvider).fix(id: _id, fixed: amount);
return max(old - result, 0);
});
}
}
Loading
Loading