TheAndersMan
TheAndersMan

Reputation: 406

Make div scroll to bottom automatically (react)

I'm currently working on a chat app for school, but I want to make it scroll to the bottom automatically as most chat apps do. I've tried every solution I can find so far, and I have only been getting react errors. I'm new to react so there could be some mistakes I don't realize I'm making. Here is what I have

class Messages extends React.Component {
    updateScroll() {
    let element = document.querySelector(".messages");
    element.scrollTop = element.scrollHeight;
}
render() {
    const messages = store.getState().messages.map((msg) => {
      this.updateScroll();
      return (
        <Message
          name={msg.displayName}
          message={msg.text}
          time={msg.timestamp}
          pic={msg.pic}
          key={msg.timestamp}
          clas={msg.who}
        />
      );
    });
    return (
      <div className="messages">
        <div className="chat">
        </div>
        <div className="sendMessage">
          <input
            type="text"
            placeholder="Message epic channel"
            className="pendingMessage"
            onKeyPress={this.handleKeyDown}
          />
          <button onClick={this.handleMessageSend}>Send</button>
        </div>
      </div>
    );
  }
}
export default Messages;

Here is my GitHub link if you want the full code as well. https://github.com/dougalcaleb/react-chat-app

Thanks!

Upvotes: 1

Views: 1706

Answers (4)

Saurish Kar
Saurish Kar

Reputation: 766

Try calling the updateScroll function inside componentDidMount if you are just fetching messages from state.

You can also use a ref to your message div and get the height from there instead of using querySelector

Upvotes: 0

Sammelan Yogi
Sammelan Yogi

Reputation: 36

create a dummy div below messages.

<div ref={messagesEndRef}></div>

    const messagesEndRef = useRef(null)

    const [msglist, setMsglist] = useState([]);

if msglist is the list of new messages, use useEffect to handle the change.

    useEffect(() => {
        messagesEndRef.current.scrollIntoView({ behavior: 'smooth' })
    }, [msglist])

Upvotes: 1

jean-smaug
jean-smaug

Reputation: 411

You should use refs instead of document query

class Messages extends React.Component {
    constructor() {
        super()
        this.messagesRef = React.createRef()
    }

    updateScroll() {
      this.messagesRef.current.scrollTo(0, this.messagesRef.current.scrollHeight)
    }

   render() {
    const messages = store.getState().messages.map((msg) => {
      this.updateScroll();
      return (
        <Message
          name={msg.displayName}
          message={msg.text}
          time={msg.timestamp}
          pic={msg.pic}
          key={msg.timestamp}
          clas={msg.who}
        />
      );
    });

    return (
      <div ref={this.messagesRef} className="messages">
        <div className="chat">
        </div>
        <div className="sendMessage">
          <input
            type="text"
            placeholder="Message epic channel"
            className="pendingMessage"
            onKeyPress={this.handleKeyDown}
          />
          <button onClick={this.handleMessageSend}>Send</button>
        </div>
      </div>
    );
  }
}
export default Messages;

Can you try that using ref + scrollTo ?

Upvotes: 1

Jayr
Jayr

Reputation: 608

I suggest you should do this with css

The chatbox content need the following markup, where the content is aligned to bottom.

.container {
  height: 100px;
  overflow: auto;
  display: flex;
  flex-direction: column-reverse;
}

Upvotes: 2

Related Questions