簡體   English   中英

在多頻道聊天應用程序中,如何顯示僅與特定聊天頻道有關的消息?

[英]In a multichannel chat application how can I display messages pertaining only to a specific chat channel?

環境:expo 36.0.0 / React Native 0.61 / react-native-gifted-chat 0.13.0 / firebase 7.6.0

我的目標:僅在天才聊天 UI 上呈現特定於特定聊天頻道的消息。

預期結果:天才聊天 UI 上應僅顯示與給定頻道有關的消息。

實際結果 :

  1. 當我從一個聊天頻道導航到另一個聊天頻道時,總消息會累積。
  2. 當我回到較早的頻道時,同一聊天頻道的消息重復不止一次。
  3. 警告:遇到兩個具有相同密鑰%s孩子。 鍵應該是唯一的,以便組件在更新時保持其身份。 非唯一鍵可能會導致子項重復和/或省略 — 該行為不受支持並且可能在未來版本中更改。%s

到目前為止我嘗試了什么? 1. 每次用戶使用 componentDidUpdate 從一個頻道導航到另一個頻道時,重新啟動對新聊天頻道的訂閱。 2. 每次用戶更改聊天頻道時,將消息數組的狀態設置為空數組。 3. 在 Firebase 中取消訂閱上一個節點並在 componentDidUpdate 中訂閱一個新節點。 這里的節點代表 Firebase 中由 ID 標識的聊天頻道。 每個節點都包含與該特定聊天頻道有關的所有消息的子節點。

  async componentDidMount() {
    await this.getSessionInfo();
    await this.getCurrentProfile();
    await this.getMessages();
  };

  async componentDidUpdate(prevProps) {
    /* sessionID represent a chat channel and corresponding node in Firebase */
    /* If user navigates from one channel to another we establish a connection with new node and get the 
    corresponding messages */
    if (this.props.navigation.state.params.sessionID !== prevProps.navigation.state.params.sessionID) {
      await this.getSessionInfo();
      await this.getCurrentProfile();
      /* Subscribe to new chat channel */
      await this.ref();
      await this.getMessages();
    }
  };

  async componentWillUnmount() {
    /* Unsubscribe from database */
    await this.off();
  }

  /* Get messages to display after component is mounted on screen */
  getMessages = () => {
    this.connect(message => {
      this.setState(previousState => ({
        messages: GiftedChat.append(previousState.messages, message),
      }))
    });
  }

  /* Each sessionID corresponds to a chat channel and node in Firebase  */
  ref = () => {
    return database.ref(`/sessions/${this.state.sessionID}`);
  }

  /* Fetch last 20 messages pertaining to given chat channel and lister to parse new incoming message */
  connect = (callback) => {
    this.ref()
      .limitToLast(20)
      .on('child_added', snapshot => callback(this.parse(snapshot)));
  }

    /* newly created message object in GiftedChat format */
    parse = snapshot => {
    const { timestamp: numberStamp, text, user } = snapshot.val();
    const { key: _id } = snapshot;
    const timestamp = new Date(numberStamp);

    const message = {
      _id,
      timestamp,
      text,
      user,
    };
    return message;
  };

  /* function that accepts an array of messages then loop through messages */
  send = (messages) => {
    for (let i = 0; i < messages.length; i++) {
      const { text, user } = messages[i];
      const message = {
        text,
        user
      };
      this.append(message);
    }
  };

  /* append function will save the message object with a unique ID */
  append = message => this.ref().push(message);

按照 Brett Gregson 的建議和 Mike Kamerman 的回答,我實施了以下解決方案。

  1. 當用戶從一個頻道導航到另一個頻道時,我會觸發一組功能。 this.ref() 函數訂閱新頻道(Firebase 中的節點)。
  async componentDidUpdate(prevProps) {
    if (this.props.navigation.state.params.sessionID !== prevProps.navigation.state.params.sessionID) {
      await this.getSessionInfo();
      await this.ref();
      await this.switchSession();
    }
  };
  1. 我將消息狀態(消息數組)設置為空數組以及異步/等待機制。 getMessages 函數獲取新通道的消息。 這樣,屬於前一組的消息將被清除,並且 UI 中沒有消息堆積。
  switchSession = async () => {
    await this.setState({ messages: [] });
    await this.getMessages();
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM