简体   繁体   中英

Firebase only fetches data on second or third attempt

I'm building an app with React and Firestore.

In one feature, I need to use some specific user data to query data from another collection, and show that on the app.

Specifically I want to use users.books, which returns an array, to query the collection books.

However, for some reason the users.books doesn't load on first render. It typically takes 2-3 renders to fetch the books.user data. This is despite the currentUserUID being loaded right away.

I've tried using a loading state as specified in How to wait for Firebase data to be fetched before progressing? , but to no avail.

Do I need to use the onSnapShot method?

Thanks for reading

My code

import 'firebase/firestore'

import { booksRef} from '../../App';

const ProfileScreen = ({ navigation }) => {
  const currentUserUID = firebase.auth().currentUser.uid;
  const [firstName, setFirstName] = useState('');
  const [userBookTitles, setUserBookTitles] = useState([]);
  const [userBooks, setUserBooks] = useState([]);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    async function getUserInfo(){
      let doc = await firebase
      .firestore()
      .collection('users')
      .doc(currentUserUID)
      .get();
      
      if (!doc.exists){
        Alert.alert('No user data found!')
      } else {
        let dataObj = doc.data();
        setFirstName(dataObj.firstName)
        setUserBookTitles(dataObj.books)
        console.log(userBookTitles)
      }
    }
    getUserInfo();
  }, [])

  useEffect(() => {
    async function getUserBooks() {
    booksRef.where("title", "in", userBookTitles).onSnapshot(snapshot => (
    setUserBooks(snapshot.docs.map((doc) => ({id: doc.id, ...doc.data()})))
    ))
  }
  setLoading(false);
  getUserBooks()
  }, [])


      if (!loading) {
      return (
          <View style={styles.container}>
            <Text> Hi {firstName} </Text>
            <TouchableOpacity onPress={handlePress}>
            
              <Text> Log out </Text>
            </TouchableOpacity>
            <Row
                    books={userBooks}
            />
          </View>
      );  
    } else { 
      return (
        <View style={styles.container}>
          <Text> Test </Text>
        </View>
    );
    }
  };

So it's worth noting that your setX methods may, or may not, complete in the sequence you have them in your code. Therefore, your booksRef call could be being made even though userBookTitles is an empty array. Which would explain why you're not getting any data on load.

You're setting userBookTitles in your first useEffect and the only other place I see you're using it is in your booksRef call. One easy fix would be to simple move booksRef inside the else statement of the first useEffect and simply pass it the userBookTitles there. This should help in solving your issue, if I understood it correctly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM