r2Dragon
r2Dragon

Reputation: 113

React - Firestore - async get data and log it outside the async function

I am trying to get data from userRef and use it to make another async call to another doc (eg: bikes) and then render that bikes doc on the page

Right now in the Home screen function the userDetailslog prints {"_U": 0, "_V": 0, "_W": null, "_X": null}. Which im assuming is because its being fired before the data is returned.

ideas on how i can structure it better to get appropriate data printed into HomeScreen?

Any help is appreciated

const userData = async () => {
  const user = auth().currentUser;
  var userRef = firestore().collection('users').doc(user.uid);

  try {
    var doc = await userRef.get();
    if (doc.exists) {
      console.log(doc.data()); // Prints Perfectly
      return doc.data();
    } else {
      console.log('No such document!');
    }
  } catch (error) {
    console.log('Error getting document:', error);
  }
};

const HomeScreen = () => {
  const userDetails = userData(); // 

  useEffect(() => {
    console.log(userDetails); // Doesn't print here
  }, [userDetails]);

  const navigation = useNavigation();


  return (
    <View>
      <Text>Home Screen</Text>
      <Button title="logout" onPress={logout} />
    </View>
  );
};

Upvotes: 0

Views: 952

Answers (2)

r2Dragon
r2Dragon

Reputation: 113

Update

I ended up using the useEffect hook with async/await like below Posting for anyone who might have a similar problem

This is what i am doing with the code below

i am accessing a doc in collection "users". retrieving a "bikeid" from that doc and then using that "bikeid" to access the relevant "bikedetails" doc from collection "bikes"

const HomeScreen = () => {
  const [userD, setUserD] = useState('');
  const [bikeID, setBikeID] = useState('');
  const [items, setItems] = useState('');

  useEffect(function effectFunction() {
    async function fetchUsers() {
      const user = auth().currentUser;
      var userRef = firestore().collection('users').doc(user.uid);
      try {
        var doc = await userRef.get();
        const data = await doc.data();
        await setUserD(data); // await to set user data, useState 
        await setBikeID(data.bikeID); // userRef doc has an associated bike id
        return data.bikeID
      } catch (error) {
        Alert.alert('Error getting document:', error);
      }
    }

    async function fetchBikes(bikeid) {
      const bid = bikeid;
      var bikeRef = firestore().collection('bikes').doc(bid);
      try {
        var doc = await bikeRef.get();
        const data = await doc.data();
        return data;
      } catch (error) {
        Alert.alert('Error getting document:', error);
      }
    }

// Defining what sequence of the async get() functions - check out mozilla article
    async function sequentialStart() {
      console.log('==SEQUENTIAL ASYNCS!!!!! ==');

      const getUsers = await fetchUsers();
      console.log(getUsers);

      const getBikes = await fetchBikes(getUsers); // using return value from getUsers to be passed into fetchBikes
      console.log(getBikes);

      const site = await setItems(getBikes); // setting state of items
      console.log(items);

    }

    sequentialStart();
  }, []);

  return (
    <View>
      <Text>Home Screen</Text>

      <Text>{items.bikeName}</Text>

      <Button title="logout" onPress={logout} />
    </View>
  );
};

Articles i read async/await - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

Helped me out a lot

Upvotes: 0

ThienLD
ThienLD

Reputation: 741

You forgor to await your async function. It should be like this:

const userDetails = await userData();

Upvotes: 1

Related Questions