0

I would like that chat window scrolls down when I send a text.

Actually messages sent don't trigger the scroll, so they are hidden.

Here's an example ( I'm using the chat component of MS Fluent UI for React library )

I have found this post but I'm not able to integrate it ( don't know where is declared the endMessage ) in my case it's value is 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;
infodev
  • 4,673
  • 17
  • 65
  • 138

2 Answers2

5

You can simply use an effect with itemsChat as dependency. Just grab the chat ul element and scroll to the bottom.

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

Working copy of your code is here

gdh
  • 13,114
  • 2
  • 16
  • 28
1

The endMessage variable is a reference to the empty div they included at the end of the Chat.

You can learn more about refs in React in the React documentation: https://reactjs.org/docs/refs-and-the-dom.html

The difference in the example code on the other question is that they don't use the built-in createRef method, but instead pass a custom function which will update the .endMessage variable to point to the current element.

The way shown in the React documentation would be adding a variable at the top of your component and fill it with the useRef hook (name it endMessage to stay with the scheme from the other post) Then in the div you put as your last chat message, you can use that variable for the ref prop:

<div ref={endMessage} />

In the callback function for a successful new post, you would then call endMessage.current.scrollIntoView (note: using current is neccessary when using the built-in react ref hooks or functions. If you pass a custom function to the ref prop you can always assign the current part of the reference directly as shown in the other SO post.

I'm not familiar with the Chat component you're using, so I can't really provide any hints on how to put that div at the very bottom. The other question was about a generic/self-programmed chat tool and just assumed you have control over the chatbox and could put a static element at the end atfer rendering the list of dynamic chat messages.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Mastacheata
  • 1,866
  • 2
  • 21
  • 32
  • Thanks for the help, I have added the chat component. The problem with it is that accepts items as `props` so I don't know how to add a div at the end of the chat. – infodev May 17 '20 at 12:59
  • I guess you could attach an empty ChatItem at the bottom by giving the ChatItem the attached=bottom prop. Not sure, though if ChatItem will produce any HTML Output you could attach to, though. I guess the idea of scrolling to the end of the list by gdh might work better for you. – Mastacheata May 17 '20 at 13:04