使用React发送消息时,聊天滚动到底部

时间:2020-05-17 12:17:27

标签: javascript reactjs office-ui-fabric office-ui-fabric-react

我希望在发送文本时该聊天窗口向下滚动。

实际上,发送的消息不会触发滚动,因此它们是隐藏的。

这里是example(我正在使用MS Fluent UI for React library的聊天组件)

我找到了这个post,但是我无法集成它(不知道endMessage在哪里声明),它的值是undefined

import React from "react";
import { Avatar, Chat, Divider, Input } from "@fluentui/react-northstar";
import { AcceptIcon } from "@fluentui/react-icons-northstar";

const janeAvatar = {
  image: "public/images/avatar/small/ade.jpg",
  status: {
    color: "green",
    icon: <AcceptIcon />
  }
};

const ChatExample = () => {
  const items = [
    {
      message: (
        <Chat.Message
          content="Hello"
          author="John Doe"
          timestamp="Yesterday, 10:15 PM"
          mine
        />
      ),
      contentPosition: "end",
      attached: "top",
      key: "message-id-1"
    },
    {
      message: (
        <Chat.Message
          content="I'm back!"
          author="John Doe"
          timestamp="Yesterday, 10:15 PM"
          mine
        />
      ),
      contentPosition: "end",
      attached: true,
      key: "message-id-2"
    },
    {
      message: (
        <Chat.Message
          content={{
            content: (
              <div>
                What do you think about <a href="#">www.goodFood.com</a>?
              </div>
            )
          }}
          author="John Doe"
          timestamp="Yesterday, 10:15 PM"
          mine
        />
      ),
      contentPosition: "end",
      attached: "bottom",
      key: "message-id-3"
    },
    {
      gutter: <Avatar {...janeAvatar} />,
      message: (
        <Chat.Message
          content="Hi"
          author="Jane Doe"
          timestamp="Yesterday, 10:15 PM"
        />
      ),
      attached: "top",
      key: "message-id-4"
    },
    {
      gutter: <Avatar {...janeAvatar} />,
      message: (
        <Chat.Message
          content="Looks good!"
          author="Jane Doe"
          timestamp="Yesterday, 10:15 PM"
        />
      ),
      attached: true,
      key: "message-id-5"
    },
    {
      gutter: <Avatar {...janeAvatar} />,
      message: (
        <Chat.Message
          content={
            <div>
              I also like <a href="#">www.goodFood2.com</a>.
            </div>
          }
          author="Jane Doe"
          timestamp="Yesterday, 10:15 PM"
        />
      ),
      attached: "bottom",
      key: "message-id-6"
    },
    {
      message: (
        <Chat.Message
          content="Would you like to grab lunch there?"
          author="John Doe"
          timestamp="Yesterday, 10:16 PM"
          mine
        />
      ),
      contentPosition: "end",
      key: "message-id-7"
    },
    {
      gutter: <Avatar {...janeAvatar} />,
      message: (
        <Chat.Message
          content="Sure! Let's try it."
          author="Jane Doe"
          timestamp="Yesterday, 10:15 PM"
        />
      ),
      key: "message-id-8"
    },
    {
      children: <Divider content="Today" color="brand" important />,
      key: "message-id-9"
    },
    {
      message: (
        <Chat.Message
          content="Ok, let's go."
          author="John Doe"
          timestamp="Today, 11:15 PM"
          mine
        />
      ),
      contentPosition: "end",
      key: "message-id-10"
    }
  ];
  const [inputValue, setInputValue] = React.useState("");
  const [itemsChat, setItemsChat] = React.useState(items);
  const chatStyle = {
    height: 500,
    overflow: "scroll"
  };
  const handleKeyDown = event => {
    if (event.key == "Enter") {
      console.log(event);
      let elm = {
        message: (
          <Chat.Message
            content={inputValue}
            author="John Doe"
            timestamp="Yesterday, 10:15 PM"
            mine
          />
        ),
        contentPosition: "end",
        attached: "top",
        key: "message-id-1"
      };
      setItemsChat(itemsChat => [...itemsChat, elm]);
      setInputValue("");
    }
  };
  return (
    <div>
      <Chat style={chatStyle} items={itemsChat} />

      <Input
        fluid
        placeholder="Inverted color input..."
        value={inputValue}
        onKeyDown={event => handleKeyDown(event)}
        onChange={event => setInputValue(event.target.value)}
      />
    </div>
  );
};

export default ChatExample;

2 个答案:

答案 0 :(得分:3)

您可以简单地使用带有itemsChat作为依赖项的效果。只需抓住聊天ul元素并滚动到底部即可。

useEffect(() => {
    document.querySelector('.ui-chat').scrollTop = document.querySelector('.ui-chat').scrollHeight
  }, [itemsChat])

Working copy of your code is here

答案 1 :(得分:0)

endMessage变量是对它们在聊天末尾包含的空div的引用。

您可以在React文档中进一步了解React中的引用:https://reactjs.org/docs/refs-and-the-dom.html

在另一个问题上,示例代码的不同之处在于它们不使用内置的createRef方法,而是传递了一个自定义函数,该函数将更新.endMessage变量以指向当前元素。

React文档中显示的方式是在组件顶部添加一个变量,并用useRef钩子填充(将其命名为endMessage以与另一篇文章中的方案保持一致) 然后在div作为最后一个聊天消息,您可以将该变量用于ref prop:

<div ref={endMessage} />

在成功发布新帖子的回调函数中,您将调用endMessage.current.scrollIntoView(注意:当使用内置的react ref钩子或函数时,必须使用current。如果将自定义函数传递给ref prop,您始终可以直接分配参考的当前部分,如其他SO帖子中所示。

我对您使用的聊天组件不熟悉,因此我无法提供有关如何将div放在最底端的任何提示。另一个问题是关于通用/自编程聊天工具的,只是假设您可以控制聊天框,并且可以在最后放置一个静态元素以呈现动态聊天消息的列表。