【Flutter】Firebaseを使ってユーザー登録を実装(Riverpod, state_notifier, freezed)

こちらの方に詳細があるので是非ご覧下さい。

signup_page.dartは以下のようになっています。それぞれの項目を入力し登録ボタンを押すと、ssp.signUp();が呼ばれ、登録完了したら、ダイアログが表示されOKを押すと、RootPage()に遷移する。

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/all.dart';
import 'package:xxx/provider/signup_provider.dart';
import 'package:xxx/root.dart';
import 'package:xxx/widget/dialog.dart';

class SignUpPage extends HookWidget {
 final usernameController = TextEditingController();
 final passwordController = TextEditingController();
 final passwordConfirmController = TextEditingController();
 final mailController = TextEditingController();
 final dialog = MyDialog();
 
 @override
 Widget build(BuildContext context) {
   final ssp = useProvider(signUpStateProvider);
   final signUpState = useProvider(signUpStateProvider.state);
   return Scaffold(
     appBar: AppBar(
       title: Text('サインアップ'),
     ),
     body: Padding(
       padding: const EdgeInsets.all(8.0),
       child: Column(
         children: <Widget>[
           Row(
             mainAxisAlignment: MainAxisAlignment.end,
             children: [
               Text(
                 '*',
                 style: TextStyle(
                   color: Colors.red,
                 ),
               ),
               Text('は必須'),
               Padding(
                 padding: const EdgeInsets.all(8.0),
                 child: RaisedButton(
                   child: Text('登録'),
                   onPressed: () async {
                     try {
                       await ssp.signUp(
                           signUpState.username,
                           signUpState.password,
                           signUpState.passwordConfirm,                           
                           signUpState.email);
                       await dialog.show(context, '登録完了しました');
                       Navigator.pushReplacement(
                           context,
                           MaterialPageRoute(
                               builder: (context) => RootPage()));
                     } catch (e) {
                       dialog.show(context, e.toString());
                     }
                   },
                 ),
               ),
             ],
           ),
           Row(
             children: <Widget>[
               Text(' * '),
               SizedBox(
                 width: 320,
                 height: 50,
                 child: TextField(
                   decoration: InputDecoration(hintText: 'IDを半角英数字で入力してください'),
                   // obscureText: true,
                   controller: usernameController,
                   onChanged: (text) {
                     ssp.setText('username', text);
                   },
                 ),
               ),
             ],
           ),
           Row(
             children: <Widget>[
               Text(' * '),
               SizedBox(
                 width: 320,
                 height: 50,
                 child: TextField(
                   decoration:
                       InputDecoration(hintText: 'パスワードを6文字以上で入力してください'),
                   obscureText: true,
                   controller: passwordController,
                   onChanged: (text) {
                     ssp.setText(’password', text);
                   },
                 ),
               ),
             ],
           ),
           Row(
             children: <Widget>[
               Text(''),
               SizedBox(
                 width: 320,
                 height: 50,
                 child: TextField(
                   decoration: InputDecoration(hintText: 'パスワードを再入力してください'),
                   obscureText: true,
                   controller: passwordConfirmController,
                   onChanged: (text) {
                     ssp.setText('passwordConfirm', text);
                   },
                 ),
               ),
             ],
           ),           
           Row(
             children: [
               Text(''),
               SizedBox(
                 width: 320,
                 height: 50,
                 child: TextField(
                   decoration: InputDecoration(hintText: 'example@co.jp'),
                   controller: mailController,
                   onChanged: (text) {
                     ssp.setText('mail', text);
                   },
                 ),
               ),
             ],
           ),
         ],
       ),
     ),
   );
 }
}

signup_provider.dartは以下の通り。ポイントはwidget外からプロバイダーを呼ぶ時はread(authProvider).signUp();のようにすること。authProviderにfirebaseとの連携部分がある。

import 'package:hooks_riverpod/all.dart';
import 'package:xxx/client/auth.dart';
import 'package:xxx/entity/auth.dart';
import 'package:state_notifier/state_notifier.dart';

final signUpStateProvider = StateNotifierProvider((_) => SignUpStateProvider());
class SignUpStateProvider extends StateNotifier<SignUpState> {
 SignUpStateProvider() : super(SignUpState());
 Reader read;
 
 void initState(reader) {
   read = reader;
 }
 
 Future signUp(username, password, passwordConfirm, mail) async {
   await read(authProvider).signUp(username, password, passwordConfirm, mail);
 }

 setText(key, text) {
   if (key == 'username') state = state.copyWith(username: text);
   if (key == 'password') state = state.copyWith(password: text);
   if (key == 'passwordConfirm') state = state.copyWith(passwordConfirm: text);   
   if (key == 'mail') state = state.copyWith(email: text);
 }
}

signUp()が呼ばれた時に、 

 final User user = (await _auth.createUserWithEmailAndPassword(
     email: mail,
     password: password,
   )).user;

でFirebaseにユーザー登録され、登録成功したら、userに情報が入る。さらにFirestoreにusersというコレクションを作り、ドキュメントのidをuser.uidに紐づけて追加情報をドキュメントに入れている。

auth.dartは以下の通り。

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:hooks_riverpod/all.dart';

final authProvider = Provider.autoDispose((ref) => AuthController(ref.read));

class AuthController {
 AuthController(this.read);
 final Reader read;
 final FirebaseAuth _auth = FirebaseAuth.instance;
 User currentUser = FirebaseAuth.instance.currentUser;
// 登録
 Future signUp(username, password, passwordConfirm, mail) async {
   if (username.isEmpty) {
     throw ('IDを入力して下さい');
   }
   if (password.isEmpty) {
     throw ('パスワードを入力して下さい');
   }
   if (passwordConfirm.isEmpty) {
     throw ('パスワードを入力して下さい');
   }
   if (mail.isEmpty) {
     throw ('メールアドレスを入力して下さい');
   }
   // todo:
   final User user = (await _auth.createUserWithEmailAndPassword(
     email: mail,
     password: password,
   ))
       .user;
   final email = user.email;
   FirebaseFirestore.instance.collection('users').doc(user.uid).set(
     {
       'username': username,
       'email': email,
       'createdAt': Timestamp.now(),
     },
   );
 }
}

こちらの方に詳細があるので是非ご覧下さい。​

いいなと思ったら応援しよう!