Get firebase.auth().currentUser with async/await
Y

5

14

I successfully check user's authentication state with onAuthStateChange observer and redirect user to the Dashboard page (react-native project). However, on the dashboard I already want to show some user specific data, e.g. enrolled programs/statistics. For that I need currentUser object to be initialised and populated, which takes some time (I need uid from there to get some data from Database). Thus, i'm looking for some way to wait until this process finishes successfully. What I'm trying to do it to use async/await syntax in componentDidMount, but the result returned is null. (Same syntax successfully works in other screens, but fails in the first one)

async componentDidMount() {
  try {
    let uid = await firebase.auth().currentUser.uid;
    console.log(uid);
  } catch(error) {
    console.log(error);
  }
}

What could be the best way to wait for currentUser object being loaded using async/await syntax? I believe that the reason could be that firebase returns null as the first result and then correct uid as the second one.

For now for the workaround, I'm using simple setInterval function, but I do not want to increase amount of loading time that much.

  let waitForCurrentUser = setInterval(() => {
    if ( firebase.auth().currentUser.uid !== null ) {
        clearInterval(waitForCurrentUser);
        let uid = firebase.auth().currentUser.uid;
        this.setState({uid});
        return firebase.auth().currentUser.uid;
    } else {
      console.log('Wait for it');
    }
  }, 700);
Yoshida answered 6/5, 2017 at 15:0 Comment(0)
M
0

The equivalence of setInterval is :

//calling the asynchronous function
  waitForCurrentUser(function(uid){
   if(uid)
   console.log('the user id is',uid)
  })

   async waitForCurrentUser(userIdIs){

    try {
       let uid = await firebase.auth().currentUser.uid;
       if(uid)
       {
         clearInterval(waitForCurrentUser);        
         this.setState({uid});
         userIdIs(uid); 
       }
       else {
       console.log('Wait for it');
      }

    }

    catch(e){
     console.log(e)
    }

  //  return userIdIs(uid);//returns promise
  };

Cheers :)

Merrifield answered 6/5, 2017 at 17:46 Comment(6)
Unfortunately, it does not change much. It returns currentUser.uid as null or throws error, because this object has not finished loading or the first result is null and I need second one or something like that. So, I'm not sure how could I wait for this object to finish loading.Yoshida
I think the control bypasses these statements... so it may work inside if condition..Merrifield
Where do you define userIdIs(uid)? Probably, it does not work in my case, because I have replaced it with return uidYoshida
please see the edits, i think this would surely work for you.Merrifield
Still throws an error. I have put this.waitForCurrentUser((uid) => { console.log('the user id is',uid) }) in componentDidMount() section and pasted the function itself below, but it didn't helpYoshida
I have set it to log currentUser instead of its uid, now it indicates user as null, logs ('wait for it') and stops. By the way, thanks a lot for your help and patience, I really appreciate itYoshida
A
1

In Firebase v10, by utilizing the authStateReady method, which returns a promise, we can determine when the auth object is populated with the currentUser:

1. With promise.then() :

import { getAuth } from 'firebase/auth';

// In your component:
  useEffect(() => {
    const auth = getAuth();
    auth.authStateReady().then(() => {
      // Do whatever you want here ...

      // E.g. checking whether the user is logged in or not:
      setIsAuthReady(true);
      if (auth.currentUser) {
        setIsLoggedIn(true);
      }
      // End of E.g.

    });
  }, []);

2. With await promise :

Utilizing the await keyword is also an option, given that the response is a promise:

import { getAuth } from 'firebase/auth';

// In your component:
  useEffect(() => {
    const auth = getAuth();

    const checkAuthState = async () => {
      await auth.authStateReady();
      // Do whatever you want here ...

      // E.g. checking whether the user is logged in or not:
      setIsAuthReady(true);
      if (auth.currentUser) {
        setIsLoggedIn(true);
      }
      // End of E.g.
    };

    checkAuthState();
  }, []);
Arce answered 7/1 at 19:1 Comment(0)
M
0

The equivalence of setInterval is :

//calling the asynchronous function
  waitForCurrentUser(function(uid){
   if(uid)
   console.log('the user id is',uid)
  })

   async waitForCurrentUser(userIdIs){

    try {
       let uid = await firebase.auth().currentUser.uid;
       if(uid)
       {
         clearInterval(waitForCurrentUser);        
         this.setState({uid});
         userIdIs(uid); 
       }
       else {
       console.log('Wait for it');
      }

    }

    catch(e){
     console.log(e)
    }

  //  return userIdIs(uid);//returns promise
  };

Cheers :)

Merrifield answered 6/5, 2017 at 17:46 Comment(6)
Unfortunately, it does not change much. It returns currentUser.uid as null or throws error, because this object has not finished loading or the first result is null and I need second one or something like that. So, I'm not sure how could I wait for this object to finish loading.Yoshida
I think the control bypasses these statements... so it may work inside if condition..Merrifield
Where do you define userIdIs(uid)? Probably, it does not work in my case, because I have replaced it with return uidYoshida
please see the edits, i think this would surely work for you.Merrifield
Still throws an error. I have put this.waitForCurrentUser((uid) => { console.log('the user id is',uid) }) in componentDidMount() section and pasted the function itself below, but it didn't helpYoshida
I have set it to log currentUser instead of its uid, now it indicates user as null, logs ('wait for it') and stops. By the way, thanks a lot for your help and patience, I really appreciate itYoshida
C
0
export async function getAuthUserID(): Promise<string | undefined> {
  return await new Promise( (resolve, reject) => {
    firebase.auth().onIdTokenChanged(async (user) => {
      if (!user) {
        resolve(undefined);
      } else {
        resolve(user.uid);
      }
})
  }).then((uid: string | undefined)=>uid).catch(function(e) {
    throw (e);
  });
}
Cooper answered 22/1, 2022 at 0:24 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Mines
M
0
// sleep function
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function getCurrentUser() {
  while (!auth.currentUser)
    await sleep(100);
  return auth.currentUser;
}

getCurrentUser().then(console.log)

Explanation: wait until the currentUser attr is no longer "null" before returning it using the while loop and sleep function.

Monreal answered 30/10, 2022 at 7:46 Comment(0)
E
-2
async getUid() {
        let user = await firebaseApp.auth().currentUser;
        let email = await user.uid;
}

Hope it's usefull for you

Elide answered 21/8, 2017 at 23:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.