Search code examples
javascriptfirebasegoogle-cloud-firestorefirebase-authentication

(Firebase,js) Problem with creating document that have userID as documentID


So i'm working on registration system using firebase authentication and this is what i want to achieve is:

  1. user registers with name,surname,email and password(for that im using createUserWithEmailAndPassword())
  2. once user registered, system creates document in collection "users", that documentID matches registered userID. 3.That newly created document create fields: name and surname based on user input.

I'm currently stuck at the moment of creating document and i don't know how to make it work properly.

Finally i ended up with this:

signupForm.addEventListener("submit",(e)=>{
  e.preventDefault();
  const name = signupForm.name.value;
  const surname = signupForm.surname.value;
  const email = signupForm.email.value;
  const password = signupForm.password.value;
  
  createUserWithEmailAndPassword(auth, email, password)
    .then(cred => {
      signupForm.reset();
      userId = cred.user.uid;
      
    })
    .catch(err => {
      console.log(err.message);
    });
  
  setUserData(userId,name,surname);
});

function setUserData(userId,name,surname){
  const userRef = doc(db,"users",userId);
  setDoc(userRef,{
    name: name,
    surname: surname
  }).then(() => {
    console.log("Document successfully written!");
  })
  .catch((error) => {
    console.error("Error writing document: ", error);
  });
}

it throws:

Uncaught FirebaseError: Invalid document reference. Document references must have an even number of segments, but users has 1.

I tried many solutions from stackoverflow and even chatGPT, nothing works. How can i fix this?


Solution

  • You're calling setUserData before the user account is created, before userId has a value. If you add log statements all around your code, you'll see the order in which things execute.

    createUserWithEmailAndPassword, like all JS functions that return a promise, is asynchronous and returns immediately before the work is complete. The then and catch callbacks are also asynchronous and return promises, and are invoked some time later. If you want to do something that depends on knowing the newly created user's UID, you need to do that inside the then callback.

      createUserWithEmailAndPassword(auth, email, password)
        .then(cred => {
          signupForm.reset();
          userId = cred.user.uid;
          setUserData(userId,name,surname);  // call setUserData here with the userId
        })
        .catch(err => {
          console.log(err.message);
        });