0

I am trying to all the users from a firebase doc. I suspect my problem is a limitation with my understanding with javascript though.

I've tried this with and without the async/dispatch pattern with no luck

const getUsers = () => {
    database.collection('users').onSnapshot(docs => {
      const users = [];
      docs.forEach(doc => {
        users.push({
          ...doc.data(),
          id: doc.id,
          ref: doc.ref,
        });
      });
      return users;
    });
  };

let users = getUsers();
  users &&
    users.map(user => {
      console.log('name: ', user.displayName);
    });

Ultimately, I'd like to loop through each user

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
ss_matches
  • 497
  • 2
  • 5
  • 20

2 Answers2

1

As explained by @GazihanAlankus, since the query to the Firestore database is an asynchronous operation, you need to return a Promise in your function, by using the get() method, as follows:

  const getUsers = () => {
    return   //Note the return here
      database
      .collection('users')
      .get()
      .then(querySnapshot => {
        const users = [];
        querySnapshot.forEach(doc => {
          users.push({
            ...doc.data(),
            id: doc.id,
            ref: doc.ref
          });
        });
        return users;
      });
  };

Then you need to call it as follows:

  getUsers().then(usersArray => {
    console.log(usersArray);
    usersArray.map(user => {
      console.log('name: ', user.displayName);
    });
  });

because the function returns a Promise, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then.


You can do the following test and see in which order the console.log()s are executed and what the second console.log() prints in the console:

  getUsers().then(usersArray => {
    console.log(usersArray);
    usersArray.map(user => {
      console.log('name: ', user.name);
    });
  });

  console.log(getUsers()); 
Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
0

You can't have a non-async function that gets users from Firebase. You're trying to make impossible happen.

Here's what's wrong with your code: the return users; is returning from the closure that you give to onSnapshot. It's not returning from getUsers. There is no return in getUsers, so it actually returns undefined.

The closure you give to onSnapshot runs in the future but getUsers has to return in the past. There is no way to pass that data in the past when you don't have it. You have to return a promise and deal with it in the calling code. You cannot write a getUsers that directly returns the users instantly.

Gazihan Alankus
  • 11,256
  • 7
  • 46
  • 57