Reputation: 2127
I am trying to add a record to a realtime database in firebase. I run uer authentication and after that want to insert another data record, passing the uid to the new user in the other database. Below is a piece of the call:
state = { email: '', password: '', errorMessage: null, uid: null }
handleSignUp = () => {
firebase.auth()
.createUserWithEmailAndPassword(this.state.email, this.state.password)
.then((user)=>{
//console.log('uid',user.user.uid)
this.setState({ uid: user.user.uid })
})
.then(() => this.props.navigation.navigate('Profile'))
.catch(error => this.setState({ errorMessage: error.message }))
//insert new record into our realtime database
this.addUser(this.state.uid,this.state.email,1000); //users are given 1000 in rewards to start
}
// when a user signs up they will have a record added to the user table in realtime database
addUser = (id,email,rewards) => {
console.log(id)
Firebase.database().ref('UsersList/').push({
id,
email,
rewards
}).then((data)=>{
//success callback
console.log('data ' , data)
}).catch((error)=>{
//error callback
console.log('error ' , error)
})
}
It runs and adds a user but the uid comes out null. Email and name come from text inputs in forms.
this.state.uid
is showing null
which I figure is because I haven't dealt with this in an asynchronous fashion. How would I go about repairing this so that it will run?
Upvotes: 0
Views: 397
Reputation: 599041
Calls to setState
are executed asynchronously, so by the time you call this.addUser(...)
the this.state.uid
hasn't been updated yet.
Doug's solution will work, but as an alternative you can put the call to thisaddUser9...)
into the then
handler that you already have for the setState
call, since that runs after setState
has completed.
So something like:
handleSignUp = () => {
firebase.auth()
.createUserWithEmailAndPassword(this.state.email, this.state.password)
.then((user)=>{
//console.log('uid',user.user.uid)
this.setState({ uid: user.user.uid })
})
.then(() => {
//insert new record into our realtime database
this.addUser(this.state.uid,this.state.email,1000); //users are given 1000 in rewards to start
this.props.navigation.navigate('Profile');
})
.catch(error => this.setState({ errorMessage: error.message }))
}
Since the call to Firebase actually also runs asynchronously, you may want to consider chaining the promise that returns into your current chain.
handleSignUp = () => {
firebase.auth()
.createUserWithEmailAndPassword(this.state.email, this.state.password).then((user)=>{
//console.log('uid',user.user.uid)
this.setState({ uid: user.user.uid })
}).then(() => {
//insert new record into our realtime database
return this.addUser(this.state.uid,this.state.email,1000); //users are given 1000 in rewards to start
}).then(() => {
this.props.navigation.navigate('Profile');
}).catch(error => this.setState({ errorMessage: error.message }))
}
addUser = (id,email,rewards) => {
return Firebase.database().ref('UsersList/').push({
id,
email,
rewards
});
}
Upvotes: 0
Reputation: 317497
Perhaps this is what you want instead?
this.addUser(user.user.uid, this.state.email, 1000);
I believe setState
does not take effect immediately - it's going to do its work asynchronously. If you want to pass along that uid, just pass the known value directly.
Upvotes: 1