Reputation: 762
I've been working on this off and on for a couple of days now, and even after searching, and digging, haven't figured it out.
Here are the two relevant pieces of code:
Future<FirebaseUser> signUp(String email, String password, String username) async {
FirebaseUser user = await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password).then((newUser) {
var obj = {
"active": true,
"public": true,
"email": email,
"username":username
};
_profileRef.child(newUser.uid).set(obj).then((_) {
print("inside");
//print("new userId: ${newUser}");
//return newUser;
});
});
//print("outside");
return user;
}
And:
Future<void> register() async {
final formState = _formKey.currentState;
if(formState.validate()) {
formState.save();
try {
//print("email: " + _email + ", pwd: " + _password);
//FirebaseUser user = await FirebaseAuth.instance.signInWithEmailAndPassword(email: _email,password: _password);
//String uid = await widget.auth.signIn(_email, _password);
FirebaseUser user = await widget.auth.signUp(_email, _password, _username);
print("uid: " + user.uid);
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => HomePage(auth: widget.auth, userId: user.uid, onSignedOut: widget.onSignedIn,)));
//Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => HomePage(auth: widget.auth, userId: uid, onSignedOut: widget.onSignedIn,)));
} catch(e) {
print(e);
}
}
}
The signUp() function works properly, and correctly creates the user in Firebase, along with the userProfile entry in the Firebase realtime database. However, for whatever reason, I'm never able to get the actual FirebaseUser object back in the register() function. It always returns an error like the below:
Connected Path: satisfied (Path is satisfied), interface: en0
Duration: 1.315s, DNS @0.001s took 0.004s, TCP @0.007s took 0.053s, TLS took 0.158s
bytes in/out: 5745/975, packets in/out: 9/9, rtt: 0.051s, retransmitted packets: 0, out-of-order packets: 0
[C3.1 8282B933-6D0B-4103-937C-173268FD0304 192.168.1.7:54700<->172.217.14.106:443]
Connected Path: satisfied (Path is satisfied), interface: en0
Duration: 0.441s, DNS @0.000s took 0.003s, TCP @0.005s took 0.054s, TLS took 0.152s
bytes in/out: 5040/1812, packets in/out: 9/9, rtt: 0.052s, retransmitted packets: 0, out-of-order packets: 0
flutter: NoSuchMethodError: The getter 'uid' was called on null.
Receiver: null
Tried calling: uid
flutter: inside
Upvotes: 0
Views: 2198
Reputation: 3410
The problem is that chaining .then
kind of "overrides" the previous promise's return type.
This function returns a Future<FirebaseUser>
by itself:
_firebaseAuth.createUserWithEmailAndPassword(...);
However you have a .then
chain that returns nothing which is why no value is assigned to the final result of the Future
and it remains null
:
.then((newUser) {
var obj = {
"active": true,
"public": true,
"email": email,
"username":username
};
_profileRef.child(newUser.uid).set(obj).then((_) {
print("inside");
};
// Need to return newUser here.
};
You can either add a return newUser;
:
_profileRef.child(newUser.uid).set(obj).then((_) {
print("inside");
};
return newUser;
or follow Richard's answer which gets rid of .then
altogether and use await
only instead which make your code look cleaner and easier to read especially when there is async chaining.
Upvotes: 1
Reputation: 51692
It's generally confusing to combine the use of await
with then
. Refactor your signUp
method to remove the then
.
Future<FirebaseUser> signUp(String email, String password, String username) async {
FirebaseUser user = await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
var obj = {
"active": true,
"public": true,
"email": email,
"username": username,
};
await _profileRef.child(user.uid).set(obj);
return user;
}
Upvotes: 4