【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(),
},
);
}
}
こちらの方に詳細があるので是非ご覧下さい。