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

问题描述 投票:0回答:1

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

我的目标:仅呈现特定于聊天平台上特定聊天频道的消息。

预期的结果:资优聊天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);

javascript react-native firebase-realtime-database react-native-firebase react-native-gifted-chat
1个回答
0
投票

根据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();
  }
© www.soinside.com 2019 - 2024. All rights reserved.