当 firestore 数据库发生变化时,有没有办法更新平面列表?

Is there a way to update a flatlist when there's a change in firestore database?

我有一个显示用户个人资料、姓名和最后发送的消息的列表。几乎在某种程度上,常规消息传递应用程序显示用户。我想要做的是在显示的用户发生变化时更新列表。我尝试让它在渲染时更新,但通过重置状态,它进入无限循环,在几秒钟内将我的读取操作提高到 10k。到目前为止,我已经通过拉动刷新对其进行了更新,但我希望它能够实时更新。我不确定我是否需要使用云函数(例如 onCreate)或计时器来避免快速超过我的配额限制。

import React, { Component } from "react";
import { View, FlatList } from "react-native";
import { ListItem } from "react-native-elements";
import fireStoreDB from "../database/FirestoreDB";

export default class Home extends Component {
  constructor(props) {
    super(props);
    this.state = {
      usersInfo: [],
      refreshing: false
    };
  }

  componentDidMount() {
    this.LoadUsers();
  }

  LoadUsers = () => {
    fireStoreDB
      .getAllUsersExceptCurrent()
      .then(
        users =>
          Promise.all(
            users.map(
              ({ id, username, avatar }) =>
                fireStoreDB
                  .getUserLastMessage(fireStoreDB.getUID, id)
                  .then(message => ({ id, username, avatar, message }))
            )
          )
      )
      .then(users => {
        this.setState({
          usersInfo: users.filter(x => typeof x.avatar !== "undefined"),
          refreshing: false
        });
      });
  };

  renderItem = ({ item }) => (
    <ListItem
      onPress={() => {
        this.props.navigation.navigate("Chat", {
          userTo: item.id,
          UserToUsername: item.username,
          LoadUsers: this.LoadUsers
        });
      }}
      title={item.username}
      subtitle={item.message}
      leftAvatar={{ source: { uri: item.avatar } }}
      bottomDivider
      chevron
    />
  );

  render() {
    return (
      <View>
        <FlatList
          data={this.state.usersInfo}
          renderItem={this.renderItem}
          keyExtractor={item => item.id}
          refreshing={this.state.refreshing}
          onRefresh={() => {
            this.setState({ refreshing: true });
            this.LoadUsers();
          }}
        />
      </View>
    );
  }
}

我这样做解决了。

  async componentDidMount() {
    await Font.loadAsync({
      "open-sans-semi-bold": require("../assets/fonts/OpenSans-SemiBold.ttf"),
      Roboto: require("../node_modules/native-base/Fonts/Roboto.ttf"),
      Roboto_medium: require("../node_modules/native-base/Fonts/Roboto_medium.ttf"),
      ...Ionicons.font
    });

    this.unsubscribeMsg = fireStoreDB.lastMsgListener(this.LoadUsers);
    this.unsubscribeUser = fireStoreDB.userProfileListener(this.LoadUsers);
    this.setState({ isReady: true });
  }

  componentWillUnmount() {
    this.unsubscribeUser();
    this.unsubscribeMsg();
  }

  lastMsgListener = loadUsersCallback => {
    return firebase
      .firestore()
      .collectionGroup("chats")
      .onSnapshot(() => {
        loadUsersCallback();
      });
  };

  userProfileListener = loadUsersCallback => {
    return firebase
      .firestore()
      .collection("users")
      .onSnapshot(() => {
        loadUsersCallback();
      });
  };