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

时间:2021-01-21 16:05:47

标签: javascript react-native google-cloud-firestore promise fetch

我正在使用 .onSnapshot 从 Fire 商店实时获取数据,而且效果很好,我按预期接收数据。问题是我接收了多组数据,组件没有等到所有数据都接收到才渲染。

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

我当前的代码是:

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;

2 个答案:

答案 0 :(得分:2)

使用状态 isLoading 默认为 true,然后在快照解析后将 isLoading 设置为 false,并在 isLoading true 上显示加载指示器,并在 isLoading false 时显示您的 ui。然后你将更新推送到你的状态,一旦数据完全加载,用户就会看到数据。

也会使用与此接近的东西。一件很奇怪的事情是你将每个快照更改推送到一个数组,换句话说,随着时间的推移,这个数组保存了同一对象的更改历史记录。故意的?

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

  // Follower counts, displayname, image
  const onSnapshot = useCallback((snapshot) => {
    snapshot.forEach((doc) => {
      dataRef.doc(doc.id.toLowerCase()).onSnapshot((followerDoc) => {
        const data = followerDoc.data();
        // push new document data into an array
        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
          }
        ]);
        // or set the new data to state, by just setting the document data
        setfollowingData(data);
        setIsLoading(false);
      });
    });
  }, []);

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

    const cleanup = dataRef
      .doc(urlname)
      .collection("Following")
      .onSnapshot(onSnapshot);

    return cleanup;
  }, [onSnapshot, urlname]);

  return (
    <>
      {isLoading && <p>Loading</p>}
      {!isLoading && <p>Show data {followingData.length}</p>}
    </>
  );
}

答案 1 :(得分:1)

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

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

#include <iostream>
 
int main()
{
    constexpr size_t array_size{1000000000};
    int stack[array_size];
    stack[0] = 0;
    for(size_t i{1}; i<array_size; i++)
        stack[i] = stack[i-1] + 1;

    std::cout << sizeof(stack) << "\n";
    std::cout << "Last element: " << stack[array_size - 1] << "\n";
    return 0;
}