【问题标题】:How to suscribe to new messages in chat made with Firebase Realtime DB and ReactNative?如何在使用 Firebase Realtime DB 和 React Native 进行的聊天中订阅新消息?
【发布时间】:2021-05-19 16:15:38
【问题描述】:

我正在构建一个包含聊天的 ReactNative 应用程序,我用来保存数据的数据库是 Firebase 的 Realtime DB。

当我导航到聊天屏幕时,首先我会加载一次已经存在的聊天消息:

  const [messages, setMessages] = useState();
  ...

  let chatRef = firebase.database().ref('chats/' + chatId);
  let chatData = null;

  useEffect(() => {
    chatRef.once('value').then((snapshot) => {
      if (snapshot.exists()) {
        ...

        chatData = snapshot.val();
        setMessages(chatData.messages.reverse());

        ...
      } else {
        console.log("No data available");
      }
    }).catch((error) => {
      console.error(error);
    });
  },[]);

我在引用上使用 .once 方法,但我仍然必须使用 useEffect 来避免无限循环,因为我将聊天消息设置为状态,触发屏幕打印的原因再次调用 .once 方法,否则将再次调用。

但是当我希望到达数据库的新消息在已经打开的聊天屏幕中实时显示时,我的问题就来了。为此,我尝试执行以下操作:

let messagesRef = chatRef.child('messages');

messagesRef.limitToLast(1).on('child_added', (snapshot) => {
  let data = snapshot.val();
  if(snapshot.key > chatLen){
    console.log("NEW MESSAGE IN THIS CHAT: "+data.text);
    let auxMessages = messages;
    auxMessages[-1] = data;
    setMessages(auxMessages)
  }else{
    console.log("REPEATED NOTIFICATION OF MESSAGE: "+data.text);
  }
});

作为 snapshot.key 是我刚刚收到事件的消息的编号,chatLen 是已经显示在屏幕上的聊天时长。 p>

在最后一段代码中,我尝试订阅新消息的创建,如果我收到一条消息的重复事件,我会忽略它(但我想知道为什么会发生这种情况),但如果它是新消息我想更新它在屏幕上显示的内容,所以我将它添加到状态中的消息中,但是我进入了一个我不知道如何打破的无限循环,因为我不知道如何以我的屏幕订阅新消息的方式放置另一个 useEffect 子句,但它不会在每次打印屏幕时都这样做,但同时,每次新事件到达时,它都会由代码处理最后一个“if”子句。

对不起我的英语,任何建议都将不胜感激,这是我第一次使用 firebase 实时数据库引用,我可能做错或理解错误。

【问题讨论】:

    标签: firebase react-native firebase-realtime-database chat


    【解决方案1】:

    我建议使用实时侦听器并限制您想要访问ref 的元素。这样你就只能得到最后 20 个元素,例如:

    
    const [messages, setMessages] = useState();
    
    let chatRef = firebase
      .database()
      .ref("chats/" + chatId)
      .limitToLast(20);
    let chatData = null;
    
    useEffect(() => {
      chatRef.on("child_added", (data) => {
        setMessages({ ...messages, [data.key]: data.val() });
      });
    
      chatRef.on("child_changed", (data) => {
        setMessages({ ...messages, [data.key]: data.val() });
      });
    
      chatRef.on("child_removed", (data) => {
        const { [data.key]: removed, ...rest } = messages;
        setMessages(rest);
      });
    
      //Turn off listener when leaving react component
      return () => chatRef.off();
    }, []);
    
    Object.entries(messages)
      .sort(([a], [b]) => {
        // sort object elements by key string value
        return ("" + a.attr).localeCompare(b.attr);
      })
      .map((e) => {
        const [key, val] = e;
        // key your message database key
        // val your message value
      });
    
    
    

    您还可以将数据直接存储到数组中,并通过搜索相应的key 来添加、更新和删除元素。

    确保在离开组件时关闭监听器。

    【讨论】:

    • 谢谢塔里克,我会尝试这两种方法,limitToLast 和特别是“关闭”监听器,我认为这可能是解决方案。我保证会公布结果。
    猜你喜欢
    • 2021-11-13
    • 1970-01-01
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 2017-11-14
    • 2021-02-17
    • 1970-01-01
    相关资源
    最近更新 更多