🐷
【Flutter】Firebase ログイン機能を状態管理するなら
こんにちは、タオルです。
続き
Firebaseを使っていて、ログイン機能を状態管理するなら、FirebaseAuthStateが便利です。
import 'package:firebase_auth/firebase_auth.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'auth_state_notifier.g.dart';
class AuthStateNotifier extends _$AuthStateNotifier {
Stream<User?> build() {
// FirebaseAuthのauthStateChangesをリッスンし、ユーザーの状態変更を監視
return FirebaseAuth.instance.authStateChanges();
}
}
FirebaseAuthStateはユーザーのログイン状態を保持しています。
ログイン状態があれば、ログイン入力をスキップ。なければ、ログイン画面入力ページに遷移。
import 'package:flutter/material.dart';
import 'package:flutter_question_answer/Pages/dashboard.dart';
import 'package:flutter_question_answer/Pages/home_page.dart';
import 'package:flutter_question_answer/auth_state_notifier.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class FirstPage extends StatelessWidget {
const FirstPage({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Consumer(
builder: (context, ref, child) {
/// ここでfirebaseauthStateの監視を定義
final userAsyncValue = ref.watch(authStateNotifierProvider);
WidgetsBinding.instance.addPostFrameCallback((_) {
userAsyncValue.maybeWhen(
data: (user) {
if (user != null) {
Navigator.pushReplacement(
context,
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => HomePage(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(opacity: animation, child: child);
},
transitionDuration: const Duration(milliseconds: 500),
),
);
} else {
Navigator.pushReplacement(
context,
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => DashboardPage(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(opacity: animation, child: child);
},
transitionDuration: const Duration(milliseconds: 500),
),
);
}
},
orElse: () => const SizedBox.shrink(),
);
});
return const SizedBox.shrink();
},
),
),
);
}
}
ログインするか、ログアウトするか
Consumer(
builder: (context, ref, child) {
// authStateProviderから認証状態を監視
final userAsyncValue = ref.watch(authStateNotifierProvider);
return userAsyncValue.when(
data: (User? user) {
if (user == null) {
// ユーザーがログインしていない場合、新規登録ボタンを表示
return ElevatedButton(
onPressed: () {
// 新規登録処理をここに実装
},
child: const Text('新規登録'),
);
} else {
// ユーザーがログインしている場合、ログアウトボタンを表示
return ElevatedButton(
onPressed: () async {
await FirebaseAuth.instance.signOut();
},
child: const Text('ログアウト'),
);
}
},
loading: () => const CircularProgressIndicator(),
error: (error, stack) => const Text('エラーが発生しました'),
);
},
),
Discussion
StreamNotifirer使ってる人僕以外にいるんですね。珍しい。
StreamProviderだけでもできますけどね。処理が一個しかないならこっちの方が簡単なきがしますけどね。
addPostFrameCallback
これは、Consumerだから使うんですかね。はじめてみたな。面白い。Jboyさん!いつも記事などを拝見しております!
コメントありがとうございます!
めちゃくちゃ嬉しいです!
また後ほど、返信いたします!
👏
AsyncNotifierのStreamを使ってるつもりで書いています!
addPostFrameCallback は、AI生成で出てきたコードなので、よく分かりません。すいません。
こういった書き方もあるんですね!初心者なので、とても参考になります!
riverpod2以降は、riverpod使う時は、絶対extends _$Notifierを使うという雑な覚え方をしたのですが、
状況によっては、Providerを使う方がいい場合もあるのでしょうか?
riverpod2以降の書き方で足りない部分、Riverpod1のProviderの書き方を優先するときの判断がありそうで、riverpodの奥が深そうで辛いです。。泣
僕はあまり使ったことないので、活用例はあまり知らないですね。AWSとgo routerを組み合わせたコードで使ってる人がいましたね。
僕の記事はこれかな。
まあ、StateNotifierでAsyncValueがわかれば、AsyncNotifierやStromeNotifierを理解できると思いますよ。
まずは、StreamProviderとFutureProviderも使いつつ慣れていくといいかなと思います。
Firebase使うだけなら、DocmentSnaphotとかQuerySnapshotがわかれば使えるようになると思います。
DocumentSnapshotなら、collection.doc('id')で、QuerySnapshotなら、collection('').getとかsnapshotになるかな。この辺は慣れるまで、わからないですね。AIに質問しながら、データ型に慣れていけるといいですね。
僕は自分で試しましたね。
検索するといつもJboyさんの記事がたくさん出てくるので、勉強させてもらっています!
データ型になれるように、いろいろ触ってみようと思います!
コメントありがとうございます!嬉しいです!!
👏
addPostFrameCallbackについての使い方の答えが自分なりに出ました。
よければ見ていただきたいです。
見ます!
公開されてないのか💦
感想
なるほど〜
やはり、AutoRouteは、画面遷移のコード書かないといけないんですね。go_routerとは違いますね。
それは置いておいて、
デバッグすると、buildメソッドの中に処理書いていると何度も呼ばれますもんね。
WidgetsBinding.instance.addPostFrameCallback
を使えば、buildが終わった後に、画面遷移するから、アプリのパフォーマンス落とすようなことはしないってことかな。とても勉強になりました\(^^)/
早速返信ありがとうございます!
記事がまとまってなかったので、一旦下書きにしてましたがどこからかアクセスしてくれたんですね!
この通りです!
コミュニケーションしていただきありがとうございます!嬉しいです!!
いえいえ。タオルさんは勉強熱心で良いことです。
ライフサイクルとかオブジェクト指向がわかれば良いコード書けるんだろうな〜と日々私は、探求しております。
頑張って継続してください。