1

I am trying to call my Firestore Database from my React Native app in order to display a user's username. Below is the function I have right now. Curiously, if I console.log the value of username, then it returns the proper value.

  function getUsername() {
    getDoc(doc(db, 'usernames', user!.uid)).then((userDoc) => {
      if(userDoc.exists()) {
        const username: string = userDoc.data()[user!.uid];
        return username;
      }
      else {
        return 'error';
      }
    })};

However, I am trying to display the username/result of the function onscreen. I am calling the function like this in order to achieve that, but when I do there is no text displayed at all, not even 'error'. Is there something I'm missing?

<Text>{getUsername()}</Text>

The lack of any kind of text being displayed leads me to believe it's an issue with async/await, but when I try (to the best of my ability, at least) to convert the function to an async function, I instead get this error that crashes my app.

Objects are not valid as a react child (found: object with keys {_u, _v, _w, _x}). If you meant to render a collection of children, use an array instead.

I've tried several variations of converting this to an async function, and some others lead back to no text being displayed with no crashing.

This attempt leads to no text being displayed, but no error to be shown.

  function getUser() {
    getDoc(doc(db, 'usernames', user!.uid)).then(async(userDoc) => {
      if(userDoc.exists()) {
        await userDoc.data()[user!.uid];
      }
      else {
        return 'error';
      }
    })};

This variation leads to the error I mentioned above

  async function getUser() {
    await getDoc(doc(db, 'usernames', user!.uid)).then((userDoc) => {
      if(userDoc.exists()) {
        return userDoc.data()[user!.uid];
      }
      else {
        return 'error';
      }
    })};

Can someone point me in the right direction, or tell me why the value I log shows up in console just fine, but refuses to be printed to the actual screen?

UPDATE: Was able to come to a solution using the advice of @FrankvanPuffelen.

Below is the working code that displays the username. If I'm understanding the comments, by wrapping the desired return value, in this case the username, in a useState hook, and updating its value on retrieval of the username from Firebase, I can make sure that the function only returns when Firebase has either retrieved a value, or the request dies out, in which case 'error' is printed to the screen instead.

  const[displayUsername, setDisplayUsername] = useState<string>('');

  function getUser() {
    getDoc(doc(db, 'usernames', user!.uid)).then((userDoc) => {
      if(userDoc.exists()) {
        setDisplayUsername(userDoc.data()![user!.uid]);
      }
      else {
        return 'error';
      }
    })};
Cam
  • 21
  • 2
  • 1
    Can you try adding a `return` before `getDoc()`? And also share the 'async version' that you tried if this doesn't work? – Dharmaraj Jun 12 '22 at 19:07
  • 3
    The `return username` never makes it out of your `getUsername` function, since data is loaded from Firestore (and most modern cloud APIs) asynchronously. You'll need to use `setState` or a `useState` hook to keep the value, as shown for example in my anwers here: https://stackoverflow.com/questions/66698363/retrieve-data-from-firestore-and-setstate/66698715#66698715 and here: https://stackoverflow.com/questions/53530492/react-firestore-return-a-variable-from-a-query/53530991#53530991 – Frank van Puffelen Jun 12 '22 at 19:14
  • I added the two async variations I've tried. Also, I tried the solution you suggested, but it returned the same "Objects are not valid as a react child" error as mentioned above. – Cam Jun 12 '22 at 19:15
  • @FrankvanPuffelen Pointed me in the right direction, I'll post an answer and mark it in a few minutes. – Cam Jun 12 '22 at 21:46

0 Answers0