在多频道聊天应用程序中,如何显示仅与特定聊天频道相关的消息?

Posted

技术标签:

【中文标题】在多频道聊天应用程序中,如何显示仅与特定聊天频道相关的消息?【英文标题】:In a multichannel chat application how can I display messages pertaining only to a specific chat channel? 【发布时间】:2020-04-21 22:27:47 【问题描述】:

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

我的目标:仅在 Gifted Chat UI 上呈现特定聊天频道的特定消息。

预期结果:只有与给定频道有关的消息才应显示在 Gifted Chat UI 上。

实际结果:

    当我从一个聊天频道导航到另一个聊天频道时,消息总数会累积。 当我回到之前的频道时,同一聊天频道的消息会重复不止一次。 警告:遇到两个孩子使用相同的密钥,%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);

【问题讨论】:

尝试使用类似于 Mike Kamermans 的答案***.com/questions/29994296/… 的链接将状态设置为一个空数组 非常感谢 Brett 抽出时间回答我的问题,感谢 Ivan 和 Frank 编辑我的问题并使其更易于理解。 Mike Kamerman 答案中的概念解释帮助我实现了他的答案中出现的选项 1 的版本。 很高兴您找到了答案 【参考方案1】:

按照 Brett Gregson 的建议和 Mike Kamerman 的回答,我实施了以下解决方案。

    当用户从一个频道导航到另一个频道时,我会触发一组函数。 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();
    
  ;
    我将消息状态(一个消息数组)设置为空数组以及异步/等待机制。 getMessages 函数获取新频道的消息。这样,属于前一组的消息将被清除,并且 UI 中没有消息累积。
  switchSession = async () => 
    await this.setState( messages: [] );
    await this.getMessages();
  

【讨论】:

以上是关于在多频道聊天应用程序中,如何显示仅与特定聊天频道相关的消息?的主要内容,如果未能解决你的问题,请参考以下文章

为 webRTC 视频聊天创建频道

使用 django 频道时如何使用频道而不是组?

Django 频道实时聊天保存发送的消息

如何使用 Telegram API 通过给定的 joinlink 获取私人频道的聊天 ID?

在 Firebase 中管理聊天频道的最佳方式

在直播APP制作时如何设置直播软件聊天发言部分可见的功能