uber
uber

Reputation: 5073

How to pass additional data to a function that adds things to an object?

I am trying to create a user profile document for regular users and for merchants on Firebase. I am trying to add additional to data this document when a merchant signs up, but haven't succeeded. The difference is that merchants are supposed to have a roles array with their roles. If this is not the right approach to deal with differentiating users, I'd also be happy to hear what's best practice.

My userService file

async createUserProfileDocument(user, additionalData) {
    console.log('additionalData: ', additionalData) //always undefined
    if (!user) return
    const userRef = this.firestore.doc(`users/${user.uid}`)
    const snapshot = await userRef.get()
    if (!snapshot.exists) {
      const { displayName, email } = user
      try {
        await userRef.set({
          displayName,
          email,
          ...additionalData,
        })
      } catch (error) {
        console.error('error creating user: ', error)
      }
    }
    return this.getUserDocument(user.uid)
  }

  async getUserDocument(uid) {
    if (!uid) return null
    try {
      const userDocument = await this.firestore.collection('users').doc(uid).get()
      return { uid, ...userDocument.data() }
    } catch (error) {
      console.error('error getting user document: ', error)
    }
  }

This is what happens when the user signs up as a merchant in the RegisterMerchant component:

onSubmit={(values, { setSubmitting }) => {
        async function writeToFirebase() {
          //I can't pass the 'roles' array as additionalData
          userService.createUserProfileDocument(values.user, { roles: ['businessOnwer'] })          
          authService.createUserWithEmailAndPassword(values.user.email, values.user.password)
          await merchantsPendingApprovalService.collection().add(values)
        }
        writeToFirebase()

I am afraid this might have something to do with onAuthStateChange, which could be running before the above and not passing any additionalData? This is in the Middleware, where I control all of the routes.

useEffect(() => {
    authService.onAuthStateChanged(async function (userAuth) {
      if (userAuth) {
        //is the below running before the file above and not passing any additional data?
        const user = await userService.createUserProfileDocument(userAuth) //this should return the already created document?
        //** do logic here depending on whether user is businessOwner or not
        setUserObject(user)
      } else {
        console.log('no one signed in')
      }
    })
  }, [])

Upvotes: 1

Views: 58

Answers (1)

Józef Podlecki
Józef Podlecki

Reputation: 11283

There is onCreate callback function which is invoked when user is authenticated.

Here's how you could implement it

const onSubmit = (values, { setSubmitting }) => {

  const { user: {email, password} } = values;
  const additionalData = { roles: ['businessOnwer'] };

  auth.user().onCreate((user) => {
      const { uid, displayName, email } = user;

      this.firestore.doc(`users/${uid}`).set({
            displayName,
            email,
            ...additionalData
      });
  });

  authService.createUserWithEmailAndPassword(email, password);
}

Upvotes: 2

Related Questions