【问题标题】:React-native-gifted-chat with cloud firestore paginationReact-native-gifted-chat 与 Cloud Firestore 分页
【发布时间】:2021-02-12 02:30:26
【问题描述】:

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

一切正常。

但是,当我在聊天中发送新消息时,向上滚动查看较早的消息后,只有最后 50 条带有新消息的消息,当然,是可用的。

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

有没有办法避免这种情况?

谢谢。

这里是我的 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();
}, []);

【问题讨论】:

    标签: javascript react-native google-cloud-firestore use-effect react-native-gifted-chat


    【解决方案1】:

    您的第一次查询没问题,对于后续查询,您必须使用 ::startAt 或 ::startAfter 方法。

    您可以在官方文档中找到更多信息。 https://firebase.google.com/docs/firestore/query-data/query-cursors

    【讨论】:

      【解决方案2】:

      我在 react-native 中使用 FlatList 来呈现聊天,我不得不对聊天列表进行分页。由于实时侦听器不支持 Firestore 查询游标,我创建了两个列表,recentChatsoldChats

      我使用实时监听器query.onSnapshotoldChats 使用光标startAfter 填充recentChats。 FlatList 数据是两个列表的组合,我负责合并逻辑。

      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>
        );
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-03
        • 1970-01-01
        • 1970-01-01
        • 2018-02-15
        相关资源
        最近更新 更多