I have a profile page the shows the user his currently registered email and an edit icon that takes him to the page where he can edit the email. When the user changes the email successfully, he is returned to the previous page that showed him the registered email.
I want the user to see the new email. But the user keeps seeing the old email until the page is reloaded.
So my first thought was to naturally replace the FutureBuilder with StreamBuilder. I was not sure how to get a stream of the current user and not the future, so I used the only stream I know for FirebaseUser --> onAuthStateChanged
Widget buildEmail() {
return StreamBuilder(
stream: FirebaseAuth.instance.onAuthStateChanged,
builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting)
return Center(
child: SpinKitRing(
color: Colors.white,
size: 30,
));
else if (snapshot.hasError)
return Center(child: Text(snapshot.error));
else {
// final email = snapshot.data.data['email'];
final email = snapshot.data.email;
return Padding(
padding: const EdgeInsets.only(left: 25.0),
child: Text('$email', style: TextStyle(color: Colors.black)),
);
}
},
);
}
This StreamBuilder behaves identically to the FutureBuilder I had before
Widget buildEmail() {
return FutureBuilder(
future: FirebaseAuth.instance.currentUser(),
builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting)
return Center(
child: SpinKitRing(
color: Colors.white,
size: 30,
));
else if (snapshot.hasError)
return Center(child: Text(snapshot.error));
else {
// final email = snapshot.data.data['email'];
final email = snapshot.data.email;
return Padding(
padding: const EdgeInsets.only(left: 25.0),
child: Text('$email', style: TextStyle(color: Colors.black)),
);
}
},
);
}
}
So I looked into the documentation of onAuthStateChanged and it states:
/// Receive [FirebaseUser] each time the user signIn or signOut
This lead me to check on my update email method and check if my user is being signed in again to the app.
static Future<void> updateEmail(String password, String newEmail, BuildContext context) async {
final user = await CurrentUser.getCurrentUser();
final ref = Firestore.instance.collection('users');
try {
AuthCredential credential = EmailAuthProvider.getCredential(email: user.email, password: password);
AuthResult result = await user.reauthenticateWithCredential(credential); // Sign in?
result.user.updateEmail(newEmail);
ref.document(user.uid).updateData({'email': newEmail});
Navigator.of(context).pop();
Fluttertoast.showToast(msg: 'Success!');
} on PlatformException catch (error) {
print(error);
changeEmailErrorDialog(context, error: error.message);
} catch (error) {
print(error);
changeEmailErrorDialog(context, error: error);
}
}
I think that I am signing in the user since this method prevents the ERROR_REQUIRES_RECENT_LOGIN
exception
AuthResult result = await user.reauthenticateWithCredential(credential); // Sign in?
Am I doing something wrong? How can I get a stream of the user? The Firebase method for obtaining the current user returns a future
FirebaseAuth.instance.currentUser();
Shouldn't there be a stream version of this method?