如何在继续之前等待获取 Firebase 数据?

我正在使用 .onSnapshot 从 Fire 存储中实时获取数据,效果很好,我正在按预期接收数据.问题是我正在接收多组数据,组件并没有等到接收到所有数据才渲染.

I am fetching data from Fire store in real-time with .onSnapshot and it works great, I am receiving the data as expected. The problem is that I am receiving multiple sets of data, and the component does not wait until all the data is received before rendering.

所以我的问题是,对于我当前的代码,它们是否可以让我在显示它们之前等待获取所有数据集?

So my question is, with my current code, is their a way in which I can wait for all sets of my data to be fetched before displaying them?

我当前的代码是:

import React, {useEffect, useState} from 'react';
import {ActivityIndicator, Dimensions, Text, View} from 'react-native';
import firestore from '@react-native-firebase/firestore';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import FolloweringScreens from './FolloweringScreens';
import {TouchableOpacity} from 'react-native-gesture-handler';

const {width, height} = Dimensions.get('screen');

function Following({urlname, navigation}) {
  const [followingData, setfollowingData] = useState([]);

  // Follower counts, displayname, image
  const fetchData = () => {
    const dataRef = firestore().collection('usernames');

    dataRef
      .doc(urlname)
      .collection('Following')
      .onSnapshot((snapshot) => {
        snapshot.forEach((doc) => {
          dataRef.doc(doc.id.toLowerCase()).onSnapshot((followerDoc) => {
            const data = followerDoc.data();
            setfollowingData((prev) => [
              ...prev,
              {
                profileName: doc.id,
                displayName: data.userName,
                followerCount:
                  data.followers !== undefined ? data.followers : 0,
                followingCount:
                  data.following !== undefined ? data.following : 0,
                image: data.imageUrl ? data.imageUrl : null,
              },
            ]);
          });
        });
      });
  };

  useEffect(() => {
    fetchData();
  }, []);

  return (
    <>
      <View
        style={{
          left: width * 0.04,
          top: 50,
          flexDirection: 'row',
          alignItems: 'center',
          width: '80%',
          height: '4%',
          marginBottom: 5,
        }}>
        {/* {console.log('followin', followingData)} */}
        <TouchableOpacity onPress={() => navigation.openDrawer()}>
          <Icon name="menu" color="#222" size={30} />
        </TouchableOpacity>
        <Text style={{left: width * 0.05}}>Following</Text>
      </View>

      {followingData === [] ? (
        <ActivityIndicator size="large" color="black" />
      ) : (
        <>
          <FolloweringScreens data={followingData} />
        </>
      )}
    </>
  );
}

export default Following;

推荐答案

所以我设法以某种方式修复它.感谢朱利安的帮助

So I managed to fix it somehow. Thanks to Julian for the help

我所做的是创建一个承诺数组,只要数据发生变化就会执行.代码是:

What I did was create an array of promises which will be executed whenever the data changes. The code is:

import React, {useCallback, useEffect, useState} from 'react';
import {ActivityIndicator, Dimensions, Text, View} from 'react-native';
import firestore from '@react-native-firebase/firestore';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import FolloweringScreens from './FolloweringScreens';
import {TouchableOpacity} from 'react-native-gesture-handler';

const {width, height} = Dimensions.get('screen');

function Following({urlname, navigation}) {
  const [followingData, setfollowingData] = useState();
  const [loading, setLoading] = useState(true);

  // Following counts, displayname, image
  const fetchData = useCallback(() => {
    const dataRef = firestore().collection('usernames');

    dataRef
      .doc(urlname)
      .collection('Following')
      .limit(25)
      .onSnapshot((snapshot) => {
        let promises = [];
        snapshot.forEach((doc) => {
          const promise = dataRef
            .doc(doc.id.toLowerCase())
            .get()
            .then((followerDoc) => {
              const data = followerDoc.data();

              return {
                profileName: doc.id,
                displayName: data.displayName
                  ? data.displayName
                  : data.userName,
                followerCount:
                  data.followers !== undefined ? data.followers : 0,
                followingCount:
                  data.following !== undefined ? data.following : 0,
                image: data.imageUrl ? data.imageUrl : null,
              };
            });
          promises.push(promise);
        });
        Promise.all(promises)
          .then((res) => setfollowingData(res))
          .then(setLoading(false));
      });
  }, []);

  useEffect(() => {
  const dataRef = firestore().collection('usernames');

    const cleanup = dataRef
      .doc(urlname)
      .collection('Following')
      .limit(25)
      .onSnapshot(fetchData);

    return cleanup;

    // fetchData();
  }, [urlname, fetchData]);

  return (
    <>
      <View
        style={styles}>
        <TouchableOpacity onPress={() => navigation.openDrawer()}>
          <Icon name="menu" color="#222" size={30} />
        </TouchableOpacity>
        <Text style={{left: width * 0.05}}>Following</Text>
          </View>

      {loading ? (
        <ActivityIndicator size="large" color="black" />
      ) : (
        <>
          <FolloweringScreens data={followingData} />
        </>
      )}
    </>
  );
}

export default Following;

相关文章