質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.12%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

解決済

FutureProviderが正しい値を返してくれない

mako_0221
mako_0221

総合スコア82

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

1回答

0リアクション

0クリップ

204閲覧

投稿2022/09/21 03:12

下記のコードのようにRiverPodのFutureProviderを使用しており、FireBaseのAuthenticationの結果を受け取り、navigator.dartでその結果を利用したいと考えております。その利用結果が示す場所はhere3なのですが、ここでなぜか必ずAsyncData<bool>(value: false)でvalueとしてfalseを返してきてしまいます。
仮に下記のsample.dartにあるように、Future型を返すような関数であれば正しく動作してくれるのですが、FutureProviderを利用すると同じように期待する動作をしてくれません。

原因及び解決方法について、アドバイスをいただけると大変ありがたいです。
よろしくお願い申し上げます。

Dart

//auth.dart import 'package:firebase_auth/firebase_auth.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:riverpod/riverpod.dart'; final authUser = FutureProvider<bool>((ref) async { //here1 try { final FirebaseAuth auth = FirebaseAuth.instance; final UserCredential _result = await auth.createUserWithEmailAndPassword( email: emailController.text, password: maskController.text, ); User _user = _result.user!; // 登録したユーザー情報 _user.sendEmailVerification(); return true; } on FirebaseAuthException catch (e) { if (e.code == 'email-already-in-use') { ref.read(completeErrorMessage.notifier).update((state) => awesomeText(icon: FontAwesomeIcons.lightbulb, text: 'EZ01:指定したメールアドレスは登録済みです',color: MyStyle.alertColor)); } else if (e.code == 'invalid-email') { ref.read(completeErrorMessage.notifier).update((state) => awesomeText(icon: FontAwesomeIcons.lightbulb, text: 'EZ02:メールアドレスのフォーマットが正しくありません',color: MyStyle.alertColor)); } else if (e.code == 'operation-not-allowed') { ref.read(completeErrorMessage.notifier).update((state) => awesomeText(icon: FontAwesomeIcons.lightbulb, text: 'EZ03:指定したメールアドレス・パスワードは現在使用できません',color: MyStyle.alertColor)); } else if (e.code == 'weak-password') { ref.read(completeErrorMessage.notifier).update((state) => awesomeText(icon: FontAwesomeIcons.lightbulb, text: 'EZ04:パスワードは6文字以上にしてください',color: MyStyle.alertColor)); } else if (e.code == 'network-request-failed') { ref.read(completeErrorMessage.notifier).update((state) => awesomeText(icon: FontAwesomeIcons.lightbulb, text: 'EZ05:通信環境を確認してください',color: MyStyle.alertColor)); } else{ ref.read(completeErrorMessage.notifier).update((state) => awesomeText(icon: FontAwesomeIcons.lightbulb, text: 'EZ10:予期しないエラーです、管理者へ問い合わせください',color: MyStyle.alertColor)); } return false; } });

Dart

//navigator.dart import 'dart:developer'; import 'dart:ui'; import 'package:cards/control/auth.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class MyNavigator extends ConsumerWidget { final Widget destinationTo; final BuildContext context; final String goBack; final List<GlobalKey<FormState>>? formKeyList; MyNavigator( {required this.destinationTo, required this.context, required this.goBack, this.formKeyList, Key? key, required}) : super(key: key); Widget build(BuildContext context, WidgetRef ref) { final getResult = ref.watch(authUser);//here2 // TextButton myNavigator(BuildContext context) { return TextButton( style: TextButton.styleFrom( foregroundColor: MyStyle.mainColor, ), onPressed: () { switch (goBack) { case "進む": for (var i = 0; i < formKeyList!.length; i++) { if (!(formKeyList![i].currentState!.validate())) { return; } } navigatorAnimation( context: context, goBack: goBack, destinationTo: destinationTo); break; case "戻る": navigatorAnimation( context: context, goBack: goBack, destinationTo: destinationTo); break; case "確認メールを送信する": print(getResult);//here3 // getResult.then( // (value) { // if (value == false) {//catchでエラー側にthrowされた場合falseをreturnして、さらにここではreturnで処理が終了 // return; // } else if (value == true) {// try -catchでエラーが非発生 // navigatorAnimation( // context: context, // goBack: goBack, // destinationTo: destinationTo); // } // }); break; } }, child: Text(goBack), ); } } void navigatorAnimation( {required BuildContext context, required String goBack, required Widget destinationTo}) { Offset? begin; Navigator.of(context).push( PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) { return destinationTo; }, transitionDuration: const Duration(milliseconds: 300), transitionsBuilder: (context, animation, secondaryAnimation, child) { goBack == "進む" ? begin = const Offset(1.0, 0.0) : 0; goBack == "戻る" ? begin = const Offset(-1.0, 0.0) : 0; goBack == "確認メールを送信する" ? begin = const Offset(1.0, 0.0) : 0; const Offset end = Offset.zero; final Animatable<Offset> tween = Tween(begin: begin, end: end) .chain(CurveTween(curve: Curves.easeInOut)); final Animation<Offset> offsetAnimation = animation.drive(tween); return SlideTransition( position: offsetAnimation, child: child, ); }, ), ); }

Dart

//sample.dart Future<bool> authUser(ref) async { try { final FirebaseAuth auth = FirebaseAuth.instance; final UserCredential _result = await auth.createUserWithEmailAndPassword( email: emailController.text, password: maskController.text, ); User _user = _result.user!; // 登録したユーザー情報 _user.sendEmailVerification(); return Future<bool>.value(true); } on FirebaseAuthException catch (e) { if (e.code == 'email-already-in-use') { ref.read(completeErrorMessage.notifier).update((state) => awesomeText(icon: FontAwesomeIcons.lightbulb, text: 'EZ01:指定したメールアドレスは登録済みです',color: MyStyle.alertColor)); } else if (e.code == 'invalid-email') { ref.read(completeErrorMessage.notifier).update((state) => awesomeText(icon: FontAwesomeIcons.lightbulb, text: 'EZ02:メールアドレスのフォーマットが正しくありません',color: MyStyle.alertColor)); } else if (e.code == 'operation-not-allowed') { ref.read(completeErrorMessage.notifier).update((state) => awesomeText(icon: FontAwesomeIcons.lightbulb, text: 'EZ03:指定したメールアドレス・パスワードは現在使用できません',color: MyStyle.alertColor)); } else if (e.code == 'weak-password') { ref.read(completeErrorMessage.notifier).update((state) => awesomeText(icon: FontAwesomeIcons.lightbulb, text: 'EZ04:パスワードは6文字以上にしてください',color: MyStyle.alertColor)); } else if (e.code == 'network-request-failed') { ref.read(completeErrorMessage.notifier).update((state) => awesomeText(icon: FontAwesomeIcons.lightbulb, text: 'EZ05:通信環境を確認してください',color: MyStyle.alertColor)); } else{ ref.read(completeErrorMessage.notifier).update((state) => awesomeText(icon: FontAwesomeIcons.lightbulb, text: 'EZ10:予期しないエラーです、管理者へ問い合わせください',color: MyStyle.alertColor)); } return Future<bool>.value(false); } }

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

moriman

2022/09/21 08:32

解決方法とありますが、関数でできるのであれば「関数でやる」ということが解決方法のような気がします。 多分関数でやるのが一般的なやり方のような気がします(よく目にする、という意味で。) 質問は、FutureProviderで同じことをすることができるかどうかを知りたい、ということですかね?
mako_0221

2022/09/21 13:40

コメント有難うございます。まだ、経験が浅く、FutureProviderを利用するしか実現できないと誤解していたのですが、関数でやるとはどのようなアプローチかぜひアドバイスを願えれば幸いです
moriman

2022/09/21 14:28

https://codewithandrea.com/articles/flutter-presentation-layer/ 典型的な認証(サインイン)フローでRiverpodを使っているので、ほぼ上記の記事の通りかと思います。 上記記事では匿名認証で、質問はユーザー登録ですが基本的には同じ流れ。 色々見てみましたが、とりあえず上記のやり方がオーソドックスなのでこれだけ押さえておけば良いのではないかと思います。 というか「Future型を返すような関数であれば正しく動作してくれるのですが」とあるので、関数を使ったらできた、ということではないんですかね? いや、どちらでも良いのですが。
mako_0221

2022/09/21 15:18

コメントありがとうございます。結論からすると題意が不明確でお詫びを申し上げます。 申し上げていた関数を利用することで、認証と画面遷移の動きは実現できております。 実はそこで動作を見たときに、「確認メールを送信する」ボタンをタップするとテンポが遅れて画面が遷移するために、CircularProgressIndicator()を描画する必要があるという問題に到達しておりました。 そこで、認証過程中にこれを表示するという問題に対して、諸々調べていたところ、FutureProviderで制御することが望ましいのかという地点に達し、CircularProgressIndicator()利用以前にFutureProviderがうまく実装できないというところでの質問でした。 そもそも、CircularProgressIndicator()でローディング中を表示するためにFutureProviderで実装することが適切ではないというご意見もあるのかもしれませんが、現状を改めて報告をさせていただきます。

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。