😎

Riverpod2.6.0から変わったこと

2024/10/22に公開

Refの書き方が変わった?

remiさんがこんな投稿をXでしておりました。

https://x.com/remi_rousselet/status/1848068559529808187

A new Riverpod version has been released, with a bunch of deprecation notices related to Ref/AutoDispose.

TL;DR: No more "MyProviderRef". Just use "Ref" instead.
による英語からの翻訳
Riverpod の新しいバージョンがリリースされましたが、Ref/AutoDispose に関連する多数の非推奨通知が含まれています。

TL;DR: 「MyProviderRef」はもう不要です。代わりに「Ref」を使用してください。


All docs/examples/lints have been updated accordingly.

Quick-fixes work too.
You can easily migrate using custom_lint --fix

それに伴い、すべてのドキュメント/サンプル/リントを更新しました。

クイックフィックスも使えます。
custom_lint --fix` を使えば簡単に移行できます。

BreakingChangeとかいうのか...

pub.devみたら破壊的変更か?
あったようだ。
https://pub.dev/packages/flutter_riverpod/changelog

  • Deprecated all Ref subclasses. Instead, use Ref itself.

  • Deprecated Ref's type argument. Use Ref without its generic parameter instead.

  • Deprecated any Ref member that used Ref's generic (such as Ref.state or Ref.listenSelf). Instead, use a Notifier.

  • Added Notifier.listenSelf, as a replacement to Ref.listenSelf.

  • Ref.watch and other methods now accept auto-dispose providers too.

  • すべてのRefサブクラスを廃止。代わりにRef自身を使用する。

  • Refの型引数を廃止。代わりにジェネリック引数のないRefを使用してください。

  • Refのジェネリックを使用していたRefメンバー(Ref.stateやRef.listenSelfなど)を非推奨としました。代わりにNotifierを使用してください。

  • Ref.listenSelfの代わりにNotifier.listenSelfを追加しました。

  • Ref.watchやその他のメソッドも自動破棄プロバイダーを受け入れるようになりました。

Provider Exampel

こんな感じで使ってみました。確かにRefだけいいのかな...

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

part 'greet.g.dart';


String hello(Ref ref) => "Hello☀️";

(keepAlive: true)
Greet greet(Ref ref) => Greet(ref);

class Greet {
  Ref ref;
  Greet(this.ref);

  void logger() {
    final hello = ref.read(helloProvider);
    debugPrint(hello);
  }
}

FutureProvider Exampel

FutureProviderを使用してAPI通信をするコードを書いた例です。なんかシンプルになったような?
以前はTodoRefなんて書いてましたね😆

モデルを定義する

import 'package:freezed_annotation/freezed_annotation.dart';

part 'todo.freezed.dart';
part 'todo.g.dart';


class Todo with _$Todo {
  const factory Todo({
    (0) int userId,
    (0) int id,
    ('') String title,
    (false) bool completed,
  }) = _Todo;

  factory Todo.fromJson(Map<String, Object?> json) => _$TodoFromJson(json);
}

Providerを定義する

今度からRefだけでいいのか?
気になったのは、flutter_riverpod.dartのモジュールをインポートすることですね。

import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_theme_app/todo.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'future.g.dart';


Future<List<Todo>> todos(Ref ref) async {
  final dio = Dio();
  final response = await dio.get('https://jsonplaceholder.typicode.com/todos/');
  return (response.data as List).map((e) => Todo.fromJson(e)).toList();
}

StreamProvider Example

よく使うことがあるCloud Firestoreを例に書いてみた。

モデルを作る。

import 'package:freezed_annotation/freezed_annotation.dart';

part 'chat.freezed.dart';
part 'chat.g.dart';


class Chat with _$Chat {
  const factory Chat({
    ('') String name,
  }) = _Chat;

  factory Chat.fromJson(Map<String, dynamic> json) => _$ChatFromJson(json);
}

こちらもRefで良いみたいだな。うっかりRiverpodをインポートしてないとRef書いただけでは怒られるのに気づく🔥
他のファイルにまとまっている機能であるモジュールを呼び出してあげよう。


example

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_theme_app/chat.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'chat.g.dart';

(keepAlive: true)
FirebaseFirestore firebaseFirestore(Ref ref) => FirebaseFirestore.instance;


Stream<List<Chat>> chat(Ref ref) {
  final store = ref.read(firebaseFirestoreProvider);
  final collection = store.collection('cart').snapshots();
  return collection
      .map((event) => event.docs.map((e) => Chat.fromJson(e.data())).toList());
}

Firebase Authはこんな感じ

Firebase Authenticationでも使うことが多かったので書き直したコードを書いてみた。少しだけだがシンプルになった気がする?
arrow functionみたいな書き方にしてみた。

example

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

part 'auth.g.dart';

(keepAlive: true)
FirebaseAuth firebaseAuth(Ref ref) => FirebaseAuth.instance;

(keepAlive: true)
Stream<User?> authState(Ref ref) =>
    ref.watch(firebaseAuthProvider).authStateChanges();

(keepAlive: true)
String? uid(Ref ref) => ref.read(firebaseAuthProvider).currentUser?.uid;

最後に

多くは解説できなかったな。

ざっくりとですが、Riverpod2.6.0からRefだけでよくなったらしい書き方を試してみた。Riverpodは進化するのが早いから常に情報を収集していないといけない。これはWebのフレームワークのNext.js、Nuxt.js、ライブラリであるReact, Vue.jsでも同じですね。

何か変更は出る。常に勉強は必要。

Riverpodが使えれば偉いというわけではないのだ。Dartのコードを書くときにNullable(nullを許容する)やfor文を使った繰り返しだったりロジックを書く為に、データ型や処理の書き方を理解していることが求められる。

こんな感じでね👇

// String?がNullableだよ
(keepAlive: true)
String? uid(Ref ref) => ref.read(firebaseAuthProvider).currentUser?.uid;

皆様も良きFlutter Lifeを😎

Discussion