LoF10
LoF10

Reputation: 2127

How do I properly access uid from firebase to add a record into another database?

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

Answers (2)

Frank van Puffelen
Frank van Puffelen

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

Doug Stevenson
Doug Stevenson

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

Related Questions