如何仅在最后一条消息上放置聊天消息头像

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

我正在 React(准确地说是 Nextjs)中制作一个聊天应用程序,到目前为止我已经完成了所有组件:聊天容器,有一个标题、一个消息列表和一个输入。该代码正在侦听新消息,每条新消息都会在消息列表组件中添加一个新消息子组件。

这是我想要实现的聊天的示意图版本。每条消息都包含文本本身和人物的头像。消息数据还包含作者,因此使用弹性显示,它将消息放置在消息列表的一侧或另一侧。我希望头像仅出现在每一侧的最后一组消息上。

我认为应该由

MessageList
组件负责每次都知道哪条消息是每一方的最后一条消息,但我不确定如何实现它。首先我尝试使用CSS,但我只能显示在每侧的最后一条消息中(
:last-child
),而不能显示在每组每侧的最后一条消息中。其次,有一个数组标记每条最后一条消息,但随后我必须重新排序并搜索前一条消息,这导致头像出现在错误的消息中。此外,为每条消息设置一个状态似乎并不是最佳和高效的。

<ChatContainer>
  <Header />
  <MessagesList >
    <Message author='me' />
    <Message author='me' />    // <- avatar here
    <Message author='them' />
    <Message author='them' />  // <- avatar here
    <Message author='me' />
    <Message author='me' />
    <Message author='me' />    // <- avatar here
  <MessageList />
  <Input />
<ChatContainer />

我的问题是,如何高效地以“reactjs 方式”跟踪每一侧每组消息的最后一条消息?

reactjs
3个回答
2
投票

要在每个组中显示头像,只需检查所有消息,如果当前消息作者!==下一条消息作者,则将头像道具添加到当前

此外,为每条消息设置一个状态似乎并不是最佳选择, 高效。

为此,我需要查看您的代码,您可以创建不同的问题(对于其他人,当他们会像这样搜索时)并在此处粘贴链接


1
投票

这是一个值得尝试的解决方案:

设置聊天消息类型如下:

type ChatMessage = {
  message: string,
  author: string,
  isLastOne: boolean // avatar only appears when this is true
}

const [messagesArr, setMessagesArr] = useState<ChatMessage[]>([]);

假设,

me
them
消息存储在这个单一的
messagesArr
状态中。

有两种可能的情况:

  1. me
    发送一条消息附加到我自己的消息中,将头像推送到更新后的
    <Message author='me' />
    (反之亦然);

  2. me
    发消息到我的消息列表之前,
    them
    先发消息,打断了我自己的消息。

代码:

const initialData = [{message: "1", author: "me", isLastOne: true}]

const [messagesArr, setMessagesArr] = useState(initialData);

const newMessage = {message: "2", author: "me", isLastOne: true}; // newMessage.isLastOne always set to true

function pushNewMessage(messagesArr, newMessage) {
  newState = [...messagesArr]; // make a copy

  // Only when user is appending it's own message should we update the previous last element
  const isUpdateOwnMessage = newState[newState.length - 1].author === newMessage.author;

  if(isUpdateOwnMessage) {
    newState[newState.length - 1].isLastOne = false; // update previous last element's isLastOne value
  }

  newState.push(newMessage);
  return newState;
}

setMessagesArr(pushNewMessage(messagesArr, newMessageFromMe))

不同情况的行动:

  1. 第一种情况:当附加到我们自己的消息时,在此之前,我们将

    previous last
    元素的
    isLastOne
    更改为 false,并且由于新消息始终将
    isLastOne
    值设置为 true,这应该正确渲染头像;

  2. 第二种情况:消息被

    them
    打断,我们可以直接推送到列表。

由于头像的出现是由

isLastOne
author
值决定的,那么,我们可以安全地将其显示在作者消息列表的末尾,并且通过在推送之前检查最后一个元素的所有者,我们可以正确更新状态。不确定这是否有意义。


0
投票

我找到了解决问题的方法。这就能完成工作。

   {conversation.map((message, index) => {
      const showAvatar = index === conversation.length - 1 || message.sender.userId !== conversation[index + 1].sender.userId;
      return (
        <div key={index}>
          {showAvatar && <div className='avatar'></div> }
          <div>
            {message.text}
          </div>
        </div>          
      )
    })}
© www.soinside.com 2019 - 2024. All rights reserved.