- 変更履歴
- hooks_riverpod のみの変更点
- flutter_riverpod , hooks_riverpod 共通の変更点
- ConsumerWidget と Consumer の build , builder メソッド引数が変更
- ProviderListener が非推奨に。代わりに ref.listen を使いましょう
- StatefulWidgetからWidgetRefを利用するための ConsumerStatefulWidget と ConsumerState が追加されました
- すべての watch 関数で select ( myProvider.select((value) => ...) ) が使用できるようになりました
- Provider/FutureProvider/StreamProvider 内で ref.state を使うことで現在公開されている値を参照できるようになりました
- StateProvider内で ref.controller にアクセスできるようになりました
- ProviderReference.mounted が削除されました
- context.read が廃止、 ref.read を使いましょう
- context.refresh が廃止、 ref.refresh を使いましょう
- StateProviderを読み込んだ時の戻り値がStateNotifierProviderと統一されました。
- StateController.update が追加され、以前の状態を使った更新が簡単になりました。
- ScopedProvider が廃止され、全てのProviderで、範囲を絞った override ができるようになった
- Future/StreamProvider (AsyncValue) についての変更点 (dev.8~)
- AsyncValueを出力する全てのProviderで await を使用できるようになりました(stable~)
- AsyncValue についてのその他の変更点
- その他の変更点
- 参考リンク
2021年11月6日、Riverpod 1.0.0 がリリースされました🎉
v1のリリースに伴い、本書では v1以降 をメインとして取り扱います。
v0.14.0
までのバージョンを使用されている場合は、 v0.14.0以前版
とタイトルに付くチャプターをご覧ください。
(今後は、間違いや誤字の訂正を除き、v1用のチャプターのみ更新していきます。)
変更履歴
- 2021年11月6日: stable の変更内容を追記
- AsyncValueを提供する全てのProviderで
await
を使用できるようになりました
- AsyncValueを提供する全てのProviderで
- 2021年10月xx日: dev.10, dev.11 の変更内容を追記
- 2021年10月7日: dev.8, dev.9 の変更内容を追記
Riverpod: v1.0.0 を使用したリポジトリです。
hooks_riverpod
のみの変更点
※ flutter_riverpod
を使っている方には影響ありません。
useProvider
が削除されました
以前は、 HookWidget
と useProvider
の組み合わせにより、各Providerを読み取ることができていました。
v1.0.0 で ref.xxx
を使用した記法に統一されたことにより、 useProvider
は廃止となります。
代わりに、 HookConsumerWidget
と ref.watch
を使用しましょう。
従来の書き方
class Example extends HookWidget {
Widget build(BuildContext context) {
final count = useProvider(counterProvider);
}
}
v1以降
class Example extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
}
}
置換例
- HookWidget -> HookConsumerWidget
- Widget build(BuildContext context) -> Widget build(BuildContext context, WidgetRef ref)
- useProvider -> ref.watch
flutter_riverpod
, hooks_riverpod
共通の変更点
ConsumerWidget
と Consumer
の build
, builder
メソッド引数が変更
ScopedReader watch
が WidgetRef ref
に変更されました。
従来の書き方
class Example extends ConsumerWidget {
Widget build(BuildContext context, ScopedReader watch) {
final count = watch(counterProvider);
}
}
v1以降
class Example extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
}
}
ProviderListener
が非推奨に。代わりに ref.listen
を使いましょう
従来の書き方
class Example extends StatelessWidget {
Widget build(BuildContext context) {
return ProviderListener<int>(
provider: counterProvider,
onChange: (context, count) {
// `counterProvider` の値が変更されたときに実行される処理
print('The new count is $count');
},
child: Text('Example Widget...'),
}
}
v1 以降
final counterProvider = StateNotifierProvider<Counter, int>((ref) => Counter());
class Example extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
ref.listen<int>(counterProvider, (count) {
// `counterProvider` の値が変更されたときに実行される処理
print('The new count is $count');
});
return Text('Example Widget...');
}
}
ConsumerStatefulWidget
と ConsumerState
が追加されました
StatefulWidgetからWidgetRefを利用するための class Example extends ConsumerStatefulWidget {
const Example({Key? key}) : super(key: key);
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends ConsumerState<Example> {
Widget build(BuildContext context) {
ref.watch(counterProvider);
return Text('Hello World');
}
}
watch
関数で select
( myProvider.select((value) => ...)
) が使用できるようになりました
すべての final userProvider = StateNotifierProvider<UserController, User>((ref) => UserController());
class Example extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final age = ref.watch(userProvider.select((user) => user.age));
}
}
ref.state
を使うことで現在公開されている値を参照できるようになりました
Provider/FutureProvider/StreamProvider 内で final counterProvider = Provider<int>((ref) {
ref.listen(otherProvider, (value) {
ref.state++;
});
return 0;
});
ref.controller
にアクセスできるようになりました
StateProvider内で final counterProvider = StateProvider<int>((ref) {
ref.listen(otherProvider, (value) {
ref.controller.state++;
});
return 0;
});
ProviderReference.mounted
が削除されました
onDispose
を使用しましょう。
final myProvider = Provider<int>((ref) {
var mounted = true;
ref.onDispose(() => mounted = false);
return 0;
});
context.read
が廃止、 ref.read
を使いましょう
context
を使ったProviderへのアクセスが廃止されました。
代わりに build メソッドの引数である WidgetRef ref
を使用しましょう。
- onPressed: context.read(myControllerProvider.notifier).save,
+ onPressed: ref.read(myControllerProvider.notifier).save,
context.refresh
が廃止、 ref.refresh
を使いましょう
RefreshIndicator(
onRefresh: () async => ref.refresh(myProvider),
child: ListView(
...
),
);
StateProviderを読み込んだ時の戻り値がStateNotifierProviderと統一されました。
final counterProvider = StateProvider((ref) => 0);
// int(状態)を返す
final counter1 = ref.watch(counterProvider);
// StateController<int> を返す
final counter2 = ref.watch(counterProvider.notifier);
// StateController<int> を返す
final counter3 = ref.watch(counterProvider.state);
// int(状態)を返す
final counter4 = ref.watch(counterProvider.state).state;
マイグレーション
// 以下のように書いていた場合は…
ref.read(counterProvider).state;
// 以下のようにマイグレーション可能だが
ref.read(counterProvider.state).state;
// こちらの方がより良さそう
ref.read(counterProvider);
StateController.update
が追加され、以前の状態を使った更新が簡単になりました。
final myProvider = StateController((ref) => 0);
ref.read(myProvider).update((state) => state + 1);
ScopedProvider
が廃止され、全てのProviderで、範囲を絞った override
ができるようになった
従来は、 ProviderScope
を使った各Providerの値の上書きはルートの ProviderScope
で行うか、ScopedProvider
を対象にしてしか使うことができませんでした。
今回の修正で、全ての XxxProvider
で ScopedProvider
と同様に、任意の箇所での ProviderScope/overrides
による値の上書きが可能になりました。
置換例
ScopedProviderをProviderに書き換えるだけでOKです。
ScopedProvider<int>((ref) => throw UnimplementedError())
↓
Provider<int>((ref) => throw UnimplementedError())
Future/StreamProvider (AsyncValue) についての変更点 (dev.8~)
- FutureProviderの戻り値の型が
Future<T>
ではなくFutureOr<T>
になりました。 -
when
メソッドのloading
とerror
にて、前 (previous) の値を使用できるようになりました。
Widget build(context, ref, WidgetRef ref) {
return ref.watch(userProvider).when(
error: (error, stacktrace, _) => Text('error: $error'),
data: (user) => Text('Hello ${user.name}!'),
loading: (previous) {
if (previous is AsyncData<User>) {
return Text('loading ... (previous: ${previous.value.name})'});
}
return CircularProgressIndicator();
}
);
}
await
を使用できるようになりました(stable~)
AsyncValueを出力する全てのProviderで (以前は FutureProvider
/ StreamProvider
に制限されていました)
class MyAsyncStateNotifier extends StateNotifier<AsyncValue<MyState>> {
MyAsyncStateNotifier(): super(AsyncValue.loading()) {
// 必要なデータを取得し、完了後 `state` を更新する
}
}
final myAsyncStateNotifierProvider = StateNotifierProvider<MyAsyncStateNotifier, AsyncValue<MyState>>((ref) {
return MyAsyncStateNotifier();
});
final myFutureProvider = FutureProvider((ref) async {
// `.future` で Future を受け取り、 `await` で非同期処理の完了を待つことができる。
final myState = await ref.watch(myAsyncStateNotifierProvider.future)
});
AsyncValue についてのその他の変更点
- dev.8~
-
AsyncValue.copyWith
が削除されました。 -
AsyncValue.error(_, stacktrace)
が位置引数ではなく名前付き引数になりました。 -
AsyncValue.data
が非推奨になりました。AsyncValue.value
やAsyncValue.asData
を使用しましょう。 -
AsyncData
,AsyncError
,AsyncLoading
が拡張可能になりました。 -
AsyncValue.whenOrNull
を追加。whenOrElse
に似ているものの、orElse
パラメータの代わりにnull
を返します。 -
AsyncValue.value
を追加。ローディングやエラーの状態を処理せずに値を読み取ることが可能です。 -
AsyncError
をconst
でインスタンス化できるようになりました。
-
- stable~
-
AsyncValue.data
が廃止されました。AsyncValue.value
を使用しましょう。
-
その他の変更点
- 最小要求 Dart SDKバージョンが
2.14.0
になりました。 -
ChangeNotifierProvider
が nullableなChangeNotifier
をサポートするようになりました。 - dev.1~
-
ProviderObserver.mayHaveChanged
が削除されました。 -
ProviderReference
は廃止され、ProviderRefBase
が優先されます -
ProviderContainer.debugProviderValues
およびProviderContainer.debugProviderElements
が削除され、代わりに、ProviderContainer.getAllProviderElements
を使用できるようになりました。 -
ref.container.refresh
を行う代わりにref.refresh
を使ってプロバイダーを更新できるようになった -
ref.onDispose
は、プロバイダーの依存関係が変更されたことが分かった時点ですぐにdispose
関数を呼び出すようになりました - 各Providerは依存関係の1つが変更されリスナーがいる場合に、状態を再計算するために次の読み込みまで待つ必要がなくなりました。
-
ProviderContainer.pump
が追加されました。各Providerがリスナーに通知するか破棄されるまで簡単にawait
するために使用できるユーティリティです。 -
family
とautoDispose
を使用したとき、状態に一貫性がない問題を修正。 -
ProviderObserver.didUpdateProvider
は、以前の値と新しい値の両方を受け取るようになりました -
Family.overrideWithProvider
は、プロバイダーの作成が必要になりました
-
- dev.8~
- すべての
overrideWithProvider
メソッドが削除されました。代わりにoverrideWithValue
を使用しましょう。 - すべてのProviderに、
dependencies
という名前のパラメータが追加されました。
そのProviderが依存するProvider
とfamily
のリストを定義することができます。
final myProvider = Provider( (ref) => ref.watch(otherProvider), dependencies: [otherProvider], );
otherProvider
が上書きされたときにmyProvider
を上書きするようにRiverpodに伝わります。-
select
の中でref.watch
やref.read
が使えなくなりました。
// `select` 内では使用できない🙅♀️ myProvider.select((value) => ref.watch(something));
- すべての
- stable
-
StreamProvider.last
が廃止されました。StreamProvider.future
を代わりに使用します。 -
StreamProvider.future
,StreamProvider.stream
,FutureProvider.future
において…-
StreamProvider
が値を出力する前に自身が再構築された場合、StreamProvider.future
は代わりに新しいstreamの "最初の値" が返されます。 -
FutureProvider
で非同期処理が完了する前に自身が再構築された場合、FutureProvider.future
は代わりに新しいFuture
の結果が返されます。
-
- 値がない限り、他のProviderと任意のProviderをオーバーライドできるようになりました。
例えば、StreamProvider<Model>
をProvider<AsyncValue<Model>>
でオーバーライドできます。
-
参考リンク