使用Cloud Firestore分页进行React-Native-gifted聊天 [英] React-native-gifted-chat with cloud firestore pagination

查看:75
本文介绍了使用Cloud Firestore分页进行React-Native-gifted聊天的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Firestore存储消息.为了优化移动应用程序的性能,我想在Firestore查询中设置一个limit(50).它运行良好,并实现了道具中可用的onLoadEarlier React-native-gifted-chat.

I'm using Firestore to store messages. In order to optimize the mobile application performances, I would like to set a limit(50) in the firestore query. It works well and implemented the onLoadEarlier React-native-gifted-chat available in the props.

一切正常.

但是,当我在聊天室中发送新消息时,向上滚动以查看较早的消息后,只有50条带有新消息的消息(当然是不正确的)可用.

But, when I send a new message in the chat, after scrolled up to see the earliers messages, only the 50 last messages with the new one, off course, are available.

因此,每次我在Firestore数据库中添加一条消息时,都会执行onSnapshot(在useeffect中)并应用限制查询.

So, each time I'm adding a message in the Firestore database, the onSnapshot (in the useeffect) is executed and apply the limit query.

有办法避免这种情况吗?

Is there a way to avoid this ?

谢谢.

这是我的useEffect:

Here my useEffect :

useEffect(() => {
    const messagesListener = firestore()
    .collection('groups')
    .doc(group._id)
    .collection('messages')
    .orderBy('createdAt', 'desc')
    .limit(50)
    .onSnapshot(querySnapshot => {
        const newMessages = querySnapshot.docs.map(doc => {
            const firebaseData = doc.data();

            const data = {
                _id: doc.id,
                text: '',
                createdAt: new Date().getTime(),
                ...firebaseData
            };

            return data;
        });

        setMessages(previousMessages => {
            return GiftedChat.append(previousMessages, newMessages);
        });
    });

    return () => messagesListener();
}, []);

推荐答案

我在react-native中使用FlatList来渲染聊天,我不得不对聊天列表进行分页.由于实时侦听器不支持Firestore查询光标,因此我创建了两个列表 recentChats & oldChats .

I am using FlatList in react-native to render chats and I had to paginate the chats list. Since Firestore query cursor is not supported in live listener, I created two list, recentChats & oldChats.

我使用实时监听器 query.onSnapshot 和&使用光标 startAfter 进行 oldChats .FlatList数据是两个列表的组合,我负责合并逻辑.

I populate recentChats using live listener query.onSnapshot & oldChats using cursor startAfter. FlatList data is combination of both list and I take care of merging logic.

const MESSAGE_LIMIT = 15;

const ChatWindow = props => {
  const { sessionId, postMessage, onSendTemplateButtonPress } = props;

  // Firestore cursor is not supported in query.onSnapshot so maintaining two chat list
  // oldChats -> chat list via cursor, recentChats -> chat list via live listener
  const [oldChats, setOldChats] = useState([]);
  const [recentChats, setRecentChats] = useState([]);

  // if true, show a loader at the top of chat list
  const [moreChatsAvailable, setMoreChatsAvailable] = useState(true);

  const [inputMessage, setInputMessage] = useState('');

  useEffect(() => {
    const query = getGuestChatMessagesQuery(sessionId)
      .limit(MESSAGE_LIMIT);
    const listener = query.onSnapshot(querySnapshot => {
      let chats = [];
      querySnapshot.forEach(snapshot => {
        chats.push(snapshot.data());
      });
      // merge recentChats & chats
      if (recentChats.length > 0) {
        const newRecentChats = [];
        for (let i = 0; i < chats.length; i++) {
          if (chats[i].sessionId === recentChats[0].sessionId) {
            break;
          }
          newRecentChats.push(chats[i]);
        }
        setRecentChats([...newRecentChats, ...recentChats]);
      } else {
        setRecentChats(chats);
        if (chats.length < MESSAGE_LIMIT) {
          setMoreChatsAvailable(false);
        }
      }
    });

    return () => {
      // unsubscribe listener
      listener();
    };
  }, []);

  const onMessageInputChange = text => {
    setInputMessage(text);
  };

  const onMessageSubmit = () => {
    postMessage(inputMessage);
    setInputMessage('');
  };

  const renderFlatListItem = ({ item }) => {
    return (<ChatBubble chat={item} />);
  };

  const onChatListEndReached = () => {
    if (!moreChatsAvailable) {
      return;
    }
    let startAfterTime;
    if (oldChats.length > 0) {
      startAfterTime = oldChats[oldChats.length - 1].time;
    } else if (recentChats.length > 0) {
      startAfterTime = recentChats[recentChats.length - 1].time;
    } else {
      setMoreChatsAvailable(false);
      return;
    }
    // query data using cursor
    getGuestChatMessagesQuery(sessionId)
      .startAfter(startAfterTime)
      .limit(MESSAGE_LIMIT)
      .get()
      .then(querySnapshot => {
        let chats = [];
        querySnapshot.forEach(snapshot => {
          chats.push(snapshot.data());
        });
        if (chats.length === 0) {
          setMoreChatsAvailable(false);
        } else {
          setOldChats([...oldChats, ...chats]);
        }
      });
  };

  return (
    <View style={[GenericStyles.fill, GenericStyles.p16]}>
      <FlatList
        inverted
        data={[...recentChats, ...oldChats]}
        renderItem={renderFlatListItem}
        keyExtractor={item => item.messageId}
        onEndReached={onChatListEndReached}
        onEndReachedThreshold={0.2}
        ListFooterComponent={moreChatsAvailable ? <ActivityIndicator /> : null}
      />
      {
        Singleton.isStaff ?
          null:
          <ChatInput
            onMessageInputChange={onMessageInputChange}
            onMessageSubmit={onMessageSubmit}
            inputMessage={inputMessage}
            style={GenericStyles.selfEnd}
            onSendTemplateButtonPress={onSendTemplateButtonPress}
          />
      }
    </View>
  );
};

这篇关于使用Cloud Firestore分页进行React-Native-gifted聊天的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆