티스토리 뷰

지난 시간에 설정했던 내 주소 [경기도 성남시 수정구 창곡동]와 범위 [도(시)/ 구(시/군)/ 동명(읍/명)]를 Firestore db의 'User' collection에 저장하려고 한다. 우선, 회원정보를 UserProvider에 저장해야한다.

 

1. 회원가입

validation 검사→authentication 추가→firestore db 'User' collection에 삽입  (set()사용)UserProvider에 저장

    _tryValidation(); //validation 검사
    try {
    final newUser = await _authentication
        .createUserWithEmailAndPassword( //authentication 추가
      email: userEmail,
      password: userPassword,
    );

    if (newUser.user != null) { //firestore 추가
      await FirebaseFirestore.instance
          .collection("User")
          .doc(newUser.user!.uid)
          .set({
        "Email": userEmail,
        "Password": userPassword,
        "NickName": userNickName,
        "Scope": "",
        "Ingredient": [],
        "MyRecipes": [],
        "Location": "",
        "Post": "",
      },

      ).onError((e, _) =>
              print("Error writing document: $e"));

      _userProvider.signup(newUser.user!.uid, 
          userEmail, userPassword, userNickName); //userProvider 저장

 

2. 로그인

validation 검사→authentication 이용해 존재 확인→ 'User' collection에서 uid를 이용해 해당 유저를 찾아 UserProvider에 저장 (get()사용)

  onTap: () async {
  _tryValidation(); //validation 검사

  try {
    final newUser = await _authentication
        .signInWithEmailAndPassword( //authentication 이용해서 회원 찾기
      email: userEmail,
      password: userPassword,
    );

    if (newUser.user != null) {
      var result = await FirebaseFirestore.instance
          .collection("User")
          .doc(newUser.user!.uid);
      await result.get().then((value) => { //firestore user 찾기
            _userProvider.login( //userProvider 저장
              newUser.user!.uid,
              value['Email'].toString(),
              value['Password'].toString(),
              value['NickName'].toString(),
              value['Location'].toString(),
              value['Scope'].toString(),
              value['Ingredient'].cast<String>(),
              value['MyRecipes'].cast<String>(),
              value['Post'].cast<String>(),
            ),
          });

Provider란?

 

provider | Flutter Package

A wrapper around InheritedWidget to make them easier to use and more reusable.

pub.dev

Flutter는 공식문서가 굉장히 자세하고 친절하게 나와있어 공식문서를 보면서 따라해도 된다.  

 

하지만 영어를 못하는 나같은 사람을 위해 ...

 

[Flutter] 회원가입과 Provider

Provider와 파이어베이스로 회원가입을 해보자!

velog.io

 

위 벨로그를 참고하면 프로바이더를 생성하는 코드는 다음과 같다.

 

  // 프로바이더 인스턴스 생성
late UserProvider _userProvider;

// 프로바이더 사용
_userProvider = Provider.of<UserProvider>(context);

// set
String email = _userProvider.email;

// get
_userProvider.email = _emailConroller.text;

 

3. UserProvider

  class UserProvider extends ChangeNotifier {
  String _uid="";
  String _email = ""; //사용자 이메일
  String _password = ""; //사용자 비밀번호
  String _location=""; //사용자 위치 (경기도 성남시 수정구 창곡동)
  String _nickname=""; //사용자 닉네임 (게시글 작성 시)
  String _scope=""; //사용자 위치 범위
  List<String> _ingredients=[]; //사용자 재료
  List<String> _recipes=[]; //사용자 스크랩한 레시피
  List<String> _posts=[]; //사용자 게시글

  String get uid=>_uid;
  String get email => _email;
  String get password => _password;
  String get location=>_location;
  String get nickname => _nickname;
  String get scope=>_scope;
  List<String> get ingredients=>_ingredients;
  List<String> get recipes=>_recipes;
  List<String> get posts=>_posts;


  void signup(String _uid, String _email, String _password, String _nickname){
    this._uid=_uid;
    this._email=_email;
    this._password=_password;
    this._nickname=_nickname;
    this._location="";
    this._scope="";
    this._ingredients=[];
    this._recipes=[];
    this._posts=[];
    notifyListeners();
  }

  void login( String _uid, String _email, String _password, String _nickname, String _location,
      String _scope, List<String> _ingredients, List<String> _recipes, List<String> _posts) {
    this._uid=_uid;
    this._email=_email;
    this._password=_password;
    this._nickname=_nickname;
    this._location=_location;
    this._scope=_scope;
    this._ingredients=_ingredients;
    this._recipes=_recipes;
    this._posts=_posts;
    notifyListeners();
  }

  void set uid(String input_uid){
    _uid=input_uid;
    notifyListeners();
  }

  void set email(String input_email) {
    _email = input_email;
    notifyListeners();
  }

  void set password(String input_password) {
    _password = input_password;
    notifyListeners();
  }

  void set location(String input_location){
    _location=input_location;
    notifyListeners();
  }

  void set nickname(String input_nickname){
    _nickname=input_nickname;
    notifyListeners();
  }

  void set scope(String input_scope){
    _scope=input_scope;
    notifyListeners();
  }

  void set ingredients(List<String> input_ingredients){
    _ingredients=input_ingredients;
    notifyListeners();
  }

  void set recipes(List<String> input_recipes){
    _recipes=input_recipes;
    notifyListeners();
  }

  void set posts(List<String> input_posts){
    _posts=input_posts;
    notifyListeners();
  }

  void addIngredient(List<String> input_ingredients){ //재료추가할 때는 list로 받기
    _ingredients.addAll(input_ingredients);
    notifyListeners();
  }

  void scrapRecipe(String recipeCode){
    _recipes.add(recipeCode);
    notifyListeners();
  }

  void addPost(String postId){
    _posts.add(postId);
    notifyListeners();
  }
}

4. 내 주소와 범위 설정하기

userProvider의 location와 scope 값 update→firestore에 변경된 값 update

  TextButton(
    onPressed: () async {
      if (_formKey.currentState!.validate()) {
        _formKey.currentState!.save();
      }
      _userProvider.scope=selectedValue.toString();
      if (selectedValue != null) {
        await FirebaseFirestore.instance
            .collection("User")
            .doc(_userProvider.uid)
            .set({
          "Location": _userProvider.location,
          "Scope": selectedValue.toString(),
        }, SetOptions(merge: true));
      }
    },

 

이때, 중요한 점은 SetOptions(merge: true))! 

이걸 추가하지 않으면 덮어쓰기가 되어서 User collection에 나머지 정보는 다 날라가고 location와 scope 값만 달랑 남게 된다. 당황하지 말고 뒤에 SetOptions(merge:true)만 붙여주면 된다!