こんにちは、株式会社Pentagonでエンジニアをしているtsurumiです。
dev版のriverpodのv1からたくさんの変更点があるとtwitterで見ました。
今回はその変更点について調査しましたので一部を解説します。
【こんな人に読んで欲しい】
・riverpodを現在使っていてv1にしようかなと思っている人
・これからriverpodを使ってみようかなーと思ってるいる人
・flutter_hooks + hooks_riverpodを活用して開発している人
【この記事を読むメリット】
・最新(2021/10/03現在)のriverpodの使い方がわかります
・サンプルコードを2種類載せているので、riverpod初心者の方やFlutter初心者の方でもすぐに試せます。
今までriverpodを活用して開発していた方々にとって、widget側の変更点が多くなりそうです。
useProviderが削除?
今回の変更点の中で私が特に驚いたのは、useProviderが削除されることです。。
私が興味を持った理由は以下の通りです。
While hooks_riverpod doesn't suffer from the problem listed at the start of the issue, the logic wants that hooks_riverpod should also use the same syntax too (both to reduce confusion and simplify maintenance).
(hooks_riverpodは冒頭に挙げた問題を抱えていませんが、論理的にはhooks_riverpodも同じ構文を使うべきです。(混乱を避けメンテナンスを簡単にするため))
As such, useProvider would be deprecated and a ConsumerHookWidget would be introduced. Which means that instead of:
(そのため、useProviderは非推奨になり、ConsumerHookWidgetが導入されます。つまり、次の代わりに:)class HooksExample extends HookWidget { @override Widget build(BuildContext context) { A value = useProvider(a); } }
we'd have: (こうすべき:)
class HooksExample extends ConsumerHookWidget { @override Widget build(BuildContext context, WidgetReference ref) { A value = ref.watch(a); } }
This would also clarify that the only purpose of hooks_riverpod is to use both hooks and Riverpod simultaneously.
(これにより明らかになったのは、hooks_riverpodの唯一の目的がフックとriverpodの両方を同時に使用するということです。)
changeNotifierで使用する例
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
final hooksSamplePageNotifierProvider =
ChangeNotifierProvider((ref) => HooksSamplePageNotifier());
class HooksSamplePageNotifier extends ChangeNotifier {
int count = 0;
void increment() {
count++;
notifyListeners();
}
}
class HooksSamplePage extends HookConsumerWidget {
const HooksSamplePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final provider = hooksSamplePageNotifierProvider;
final count = ref.watch(provider).count;
final notifier = ref.read(provider);
return Scaffold(
appBar: AppBar(title: const Text('Example')),
floatingActionButton: FloatingActionButton(
onPressed: notifier.increment,
child: const Icon(Icons.add),
),
body: Center(
child: Text('$count'),
),
);
}
}
state_notifier + freezedで使用する場合
import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
part 'hooks_sample_page.freezed.dart';
final hooksSamplePageNotifierProvider =
StateNotifierProvider<HooksSamplePageNotifier, HooksSamplePageState>(
(ref) => HooksSamplePageNotifier());
@freezed
abstract class HooksSamplePageState with _$HooksSamplePageState {
const factory HooksSamplePageState({
@Default(0) int count,
}) = _HooksSamplePageState;
}
class HooksSamplePageNotifier extends StateNotifier<HooksSamplePageState> {
HooksSamplePageNotifier() : super(const HooksSamplePageState());
void increment() {
state = state.copyWith(count: state.count + 1);
}
}
class HooksSamplePage extends HookConsumerWidget {
const HooksSamplePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final provider = hooksSamplePageNotifierProvider;
final count = ref.watch(provider).count;
final notifier = ref.read(provider.notifier);
return Scaffold(
appBar: AppBar(title: const Text('Example')),
floatingActionButton: FloatingActionButton(
onPressed: notifier.increment,
child: const Icon(Icons.add),
),
body: Center(
child: Text('$count'),
),
);
}
}
まとめ
-
useProviderを使用して状態のチェックを行っている方は、こちらのバージョンをv1にすると
useProvider
のところに赤い警告が出ます。
この問題を解決するためには、全てref.watch
に変更すれば一旦大丈夫です。関数などの使用部分についてはref.read
などを使いましょう。 -
今後、riverpodの作者はdartチームの開発に左右されますが、
ref.watch
から@watch(provider)
で状態のチェックを行えるようにしたいそうです。 - 結論として、まだ開発中なので、正式リリースが出るまでバージョンを上げなくていいかもしれませんね。
- またリリース版のv1が出たら記事を新しく書きたいと思います!