Open38

読者コメント欄|Flutter x Riverpod でアプリ開発!実践入門

村松龍之介村松龍之介

本の感想や質問をお気軽にコメントしてください☺️

1コメもないと投稿しづらいから誰か…
ファーストペンギンもとむ…🐧

Daigo WakabayashiDaigo Wakabayashi

ちょうど最近Riverpod触り始めたのでとても参考になります!
読み返しながらRiverpodさんと仲良くなるぞ〜💪

村松龍之介村松龍之介

嬉しいです☺️ Riverpodについてどこか不足していることなどありましたらお気軽にお教えください👍

ktkt

購入させていただきました!
とても参考になりました!

2点質問があるんで、ぜひ見解を聞かせてください!

  1. ChangeNotifierProviderとStateNotifierProviderの使い分けってどうされていますか?(できることが同じそうなんでこっちの方が良いなど意見があればお願いします!)

  2. StateProviderなどは外部から変更できるという点が、保守する上で危険だなと感じていて、外部変更できるProviderを利用するぐらいなら通常のProviderでSetterだけ用意して、内部的に変更できる仕組みの方が安全だと感じているんですが、そこら辺の見解があればぜひ教えてください!

村松龍之介村松龍之介

ご質問ありがとうございます!
以下、質問の意図に沿った回答になっているか不安ですが、お答えします😸

  1. 僕はState NotifierProviderで統一しています。
    1. 状態クラスをImmutableで定義して、それを活かしたい
    2. 状態は別クラス・別ファイルで定義したい
    3. 状態を変更した後に、 notifyListeners(); を書いて状態の変更を通知するより、 state = state.copyWith() で状態を上書きして通知される方が個人的に分かりやすい
  2. "通常のProviderでSetterだけ用意して"
    この場合は、Providerの内部で watch した別のStateProviderやStateNotifierの変更で更新させるようなやり方ということでしょうか?
    その場合は、結局依存したXxxProviderのStateを外部(?)から変更しなければならないため、あまり利点を感じませんでした。(StateProviderではなくProviderで要件が満たせる場合は、積極的にProviderを選択します)他の対策としてはファイル内だけであればプライベートなProviderにするか、関係のないファイルでimportさせないようにするなどでしょうか🤔
ktkt
  1. StateNotifierProviderで統一しているということですね!参考にさせていただきます!

結局依存したXxxProviderのStateを外部(?)から変更しなければならない

結局、他のXxxProviderに依存する形になるんで意味がないということですね!
こちらで腑に落ちました!

二つの質問とも、丁寧に回答していただきありがとうございました!
まだまだ勉強不足なんで、この本をもう一周させていただきます!!

haaphaap

拝読させていただき、おかげさまでRiverpod入門できました。今までsetStateオンリーで組んでいたので、Riverpodの強力さに驚きました。早速自アプリに取り入れていきます🙌

村松龍之介村松龍之介

おぉ、それは嬉しいです👏☺️ご感想も書いていただき励みになります🙌

Dan NakaharaDan Nakahara

とてもありがたく、参考にさせていただいてます☺︎

下記ページなんですが、
https://zenn.dev/riscait/books/flutter-riverpod-practical-introduction/viewer/version-update-requester

  if (!isEnabled && !hasNewVersion) {
    // 有効期間外、もしくは新しいバージョンは無い
    return UpdateRequestType.not;
  }

上のコードのifの条件文、&&じゃなくて||かもです。

村松龍之介村松龍之介

Danさん、ご購入および間違いを教えていただきありがとうございます😊

上のコードのifの条件文、&&じゃなくて||かもです。

おっしゃる通りです…!修正しました✨

shounshoun

ProviderからRiverpodへ移ろうと思っていたので本当に参考になりました😄
開発がスムーズに進むことは間違いないです!

1点質問があるのですが、もしごお時間あればご意見伺えればと思います。

Providerでは依存性の注入を提供するProxyProviderがあり、私も使っていたのですが、Riverpodではどのように依存性の注入をすればいいか迷っています。
村松さんはどのようにRiverpodで依存注入されてますでしょうか?

村松龍之介村松龍之介

依存注入についてですね。
①ProxyProviderの代替ですと、別のProviderに依存した新たなProviderの作成方法という意味でしょうか?
それであれば、Provider作成時に ref.watch(myProvider) で別のProviderを取得できますので、後は任意の加工や合成を行なって return すれば良いかと思います。

②クラスへの依存注入であれば、①と同じようにref.watchで取得した別クラスを、クラスのコンストラクタで渡す。もしくは ref.read (Reader) をクラスのコンストラクタで渡して、 _read(myProvider) のように取得する方法があります。
(ref.read を渡す方でもテストではmyProviderを差し替えできるのでテスト容易性は問題ありません)
こちらの意味・用途で合っていたでしょうか?
曲解してしまっていたら改めて教えてください👍

shounshoun

ご返信ありがとうございます!
こちらの文章不足で、意味合いがふわふわしていて申し訳ありませんでした🙇‍♀️
上記のどちらともの意味合いでした、ご回答ありがとうございました!

依存注入方法非常に参考になりました、ありがとうございました!

kentarohkentaroh

ちょうど学びたかった領域ですので非常に参考になりました。執筆ありがとうございます。
拝読中なのですが、私の理解が謝っていれば申し訳ないですが、

Chapter 15
Selectを使ってState更新の再構築を最適化する
にて

bool isAbove10 = useProvider(counterProvider.select((s) => s.state > 10));
return Text('Is counter > 5 ? $isAbove5');

とありましたが、

bool isAbove10 = useProvider(counterProvider.select((s) => s.state > 10));
return Text('Is counter > 10 ? $isAbove10');

ではないでしょうか?

村松龍之介村松龍之介

kentarohさん、ご報告ありがとうございます!
こちら誤りですね…!次回修正させていただきます👍

kentarohkentaroh

あっ勘違いじゃなくてよかったです。私も記事を書いて後で見直したときに見つけることがよくあります!執筆感謝です。

sanpei1978sanpei1978

Riverpodを使ったflutter開発で大変助かっています。多謝!


1点質問させてください。Chapter 12 の下記の箇所です。

loading error 状態時のハンドリングが不要の場合は、 data?.value を使って簡略化することもできます。

final config = ref.watch(configProvider).data?.value;

このdata?.valueはv1.0.0(stable)ではDeprecatedとなってますね。代わりにasData?.valueを使用すれば良いのでしょうか?


と、書いている最中に浮かんだ疑問ですが、、
configを得るために下記2種類の書き方があると思います。

final config = ref.watch(configProvider).asData?.value;
final config? = ref.watch(configProvider).value;

この違いは見た目そのままconfigがnullである可能性の有無だけだと思いますが、どう使い分けするものなんでしょうかね??

村松龍之介村松龍之介

v1.0.0以降で AsyncValue or Null として取り出したい時の data?.value 、こちら修正漏れでした!ご報告ありがとうございます🙏

v1.0.0以降は final config = ref.watch(configProvider).value を使用してください👌
(僕は現時点で asData?.value は全く使っていないです)

sanpei1978sanpei1978

早速の返信ありがとうございます。
あ、asData?.valueでもnullで取り出される場合ありますね。見落とし...

v1.0.0以降はfinal config = ref.watch(configProvider).valueを使用してください👌
(僕は現時点でasData?.valueは全く使っていないです)

こちらも回答ありがとうございます。asData?.valueは今後非推奨になりそうな感。

村松龍之介村松龍之介

継承先である AsyncValuevalue と同じで、違いは AsyncData に一度キャスト(厳密には違う)しているかどうかなので実態はほぼ同じです👌(なのでおそらく特に非推奨にはならないかと)

sanpei1978sanpei1978

なるほど、ありがとうございます!ソースも確認してみます😊

osakiosaki

勉強させていただいています。ありがとうございます。

こちらのChapterについてですが、
Chapter 25 StateNotifierProviderで画面に対するViewModelを作成する

  // メインカウントを+1する
  <void> increaseMainCount() async {
    state = state.copyWith(mainCount: state.mainCount++);
  }

  // サブカウントを+1する
  <void> increaseSubCount() async {
    state = state.copyWith(subCount: state.subCount++);
  }

上記のインクリメントは、以下のように前置インクリメントの誤りでしょうか?

  // メインカウントを+1する
  void increaseMainCount() async {
    state = state.copyWith(mainCount: ++state.mainCount);
  }

  // サブカウントを+1する
  void increaseSubCount() async {
    state = state.copyWith(subCount: ++state.subCount);
  }
村松龍之介村松龍之介

motuさん、コメントありがとうございます🙌
ご指摘の通り誤りで以下の通りに修正したいと思います🙏

state = state.copyWith(mainCount: state.mainCount + 1);

このチャプターは戻り値表記やProviderの命名など…他にも問題があるので、サンプルページの作成とともに全体を修正いたします📝

yusei_wyyusei_wy

この本のおかげで riverpod をなんとなくで使っていた事に気づけました。
サンプルコードも多くすぐにでも開発に組み込める内容でとても助かりました。
ありがとうございました。

NanaseNanase

とても参考になりました!ありがとうございます!
Chapter29のFreezedとはについてですが

Freezedクラスを定義する上で守らなくてはいけない記法としは

上記の文章は、以下のような文章の誤りでしょうか?

Freezedクラスを定義する上で守らなくてはいけない記法としては

RyosukeOKRyosukeOK

執筆ありがとうございます!
Riverpodの勉強に役立ててます!

細かい部分ですが、質問です。
プロバイダを更新中、 when.loading 状態をスキップさせたくない1行目の

デフォルトでは when.loading 状態には入らず、以前取得できた data/error を表示したまま、更新後の結果を待ちます。

上記に関して、"デフォルトではwhen.loading 状態に入る"ではないでしょうか?

以下Riverpodのコードです。
riverpod when skipLoadingOnReload

  R when<R>({
    bool skipLoadingOnReload = false,

確認しましたが、スキップされずloading 状態に入りました。

村松龍之介村松龍之介

RyosukeOKさん、ご報告ありがとうございます🙌 skipLoadingOnRefresh のところ、 skipLoadingOnReload と書いてしまっていたようでした🙏

以下、タイトル含めて修正しました✍️
プロバイダが refresh/invalidate により再構築されるときの loading 状態をスキップさせたくない

また、以下を追加しました👍
プロバイダが watch により再構築されるときの loading 状態をスキップさせたい

ganちゃんganちゃん

Riverpod に関して隅々まで書かれていてとても勉強になります!

一点だけミスを見つけたのでその報告です!

こちらの 『RiverpodのTest tips』の章の応用部分で

expectexcept になっていました!

確認お願いします!