Home > Software design >  Firebase: How do you create a user then use the user ID in Firestore database?
Firebase: How do you create a user then use the user ID in Firestore database?

Time:12-10

I'm making an app with Typescript, React and Firebase (auth and Firestore db). I'm planning on structuring my data so that the user id is used as the document name in the user collection.

When a user creates their account, I want to:

  1. Create a user account using Firebase auth
  2. Use the user uid that was created by Firebase auth as the document header in Firestore
  3. Create a new document in the user collection with the user's details.

As such, the code I've tried to use is this (relevant parts shown only):

function App() {

  const [user, setUser] = useState<object>({});
...

  async function signUpUser(e: FormEvent) {
    e.preventDefault();

   ...

    try {
      await createUserWithEmailAndPassword(auth, userEmail, userPassword);
      const newUser = new User(userName, userEmail, userRole, []);
      await setDoc(doc(db, "users", user.uid), {...newUser});

    } catch(error) {
      alert(error)
    }
      navigate("/location")
  }

...
 
  useEffect(() => {
    onAuthStateChanged(auth, userData => {
      const currentUser = userData as any
      setUser(currentUser)
    })
  })
  
...
export default App;

But this gives me this error after Typechecking:"TS2339: Property 'uid' does not exist on type 'object'."

I think this is because the user state has not yet been updated by the auth state observer. I thought using await would give the program enough time for it to be saved but that's not the case.

How can I fix the code so that I can immediately use the user uid in a database call?

I have changed

  const [user, setUser] = useState<object>({});

to

  const [user, setUser] = useState<any>({});

And that gets rid of the Typecheck error, but throws another one about a null object when the signUpUser function is called.

I have also tried to change signUpUser to a synchronous function that calls createUserWithEmailAndPassword and setDoc in separate async functions, but that throws the same TS2339: Property 'uid' does not exist on type 'object' error.

I've used a different function to get the uid of the currently signed in user as below:

const userID: string = auth.currentUser.uid
      await setDoc(doc(db, "users", userID), {...newUser});

But that produces this error: TS18047: 'auth.currentUser' is possibly 'null'.

CodePudding user response:

You're need to capture the result from the createUserWithEmailAndPassword, which is where you can get the UID from.

Something like this:

const credentials = await createUserWithEmailAndPassword(auth, userEmail, userPassword);
const newUser = new User(userName, userEmail, userRole, []);
await setDoc(doc(db, "users", credentials.user.uid), {...newUser});
  • Related