How to scroll to bottom in react?

前端 未结 19 786
执笔经年
执笔经年 2020-11-28 18:27

I want to build a chat system and automatically scroll to the bottom when entering the window and when new messages come in. How do you automatically scroll to the bottom of

相关标签:
19条回答
  • 2020-11-28 18:54

    Thanks to @enlitement

    we should avoid using findDOMNode, we can use refs to keep track of the components

    render() {
      ...
    
      return (
        <div>
          <div
            className="MessageList"
            ref={(div) => {
              this.messageList = div;
            }}
          >
            { messageListContent }
          </div>
        </div>
      );
    }
    
    
    
    scrollToBottom() {
      const scrollHeight = this.messageList.scrollHeight;
      const height = this.messageList.clientHeight;
      const maxScrollTop = scrollHeight - height;
      this.messageList.scrollTop = maxScrollTop > 0 ? maxScrollTop : 0;
    }
    
    componentDidUpdate() {
      this.scrollToBottom();
    }
    

    reference:

    • https://facebook.github.io/react/docs/react-dom.html#finddomnode
    • https://www.pubnub.com/blog/2016-06-28-reactjs-chat-app-infinite-scroll-history-using-redux/
    0 讨论(0)
  • 2020-11-28 18:55

    react-scrollable-feed automatically scrolls down to the latest element if the user was already at the bottom of the scrollable section. Otherwise, it will leave the user at the same position. I think this is pretty useful for chat components :)

    I think the other answers here will force scroll everytime no matter where the scrollbar was. The other issue with scrollIntoView is that it will scroll the whole page if your scrollable div was not in view.

    It can be used like this :

    import * as React from 'react'
    
    import ScrollableFeed from 'react-scrollable-feed'
    
    class App extends React.Component {
      render() {
        const messages = ['Item 1', 'Item 2'];
    
        return (
          <ScrollableFeed>
            {messages.map((message, i) => <div key={i}>{message}</div>)}
          </ScrollableFeed>
        );
      }
    }
    

    Just make sure to have a wrapper component with a specific height or max-height

    Disclaimer: I am the owner of the package

    0 讨论(0)
  • 2020-11-28 18:55

    I like doing it the following way.

    componentDidUpdate(prevProps, prevState){
      this.scrollToBottom();
    }
    
    scrollToBottom() {
      const {thing} = this.refs;
      thing.scrollTop = thing.scrollHeight - thing.clientHeight;
    }
    
    render(){
      return(
        <div ref={`thing`}>
          <ManyThings things={}>
        </div>
      )
    }
    
    0 讨论(0)
  • 2020-11-28 18:56

    If you want to do this with React Hooks, this method can be followed. For a dummy div has been placed at the bottom of the chat. useRef Hook is used here.

    Hooks API Reference : https://reactjs.org/docs/hooks-reference.html#useref

    import React, { useEffect, useRef } from 'react';
    
    const ChatView = ({ ...props }) => {
    const el = useRef(null);
    
    useEffect(() => {
        el.current.scrollIntoView({ block: 'end', behavior: 'smooth' });
    });
    
     return (
       <div>
         <div className="MessageContainer" >
           <div className="MessagesList">
             {this.renderMessages()}
           </div>
           <div id={'el'} ref={el}>
           </div>
         </div>
        </div>
      );
    }
    
    0 讨论(0)
  • 2020-11-28 19:00

    I created a empty element in the end of messages, and scrolled to that element. No need of keeping track of refs.

    0 讨论(0)
  • 2020-11-28 19:01

    This is how you would solve this in TypeScript (using the ref to a targeted element where you scroll to):

    class Chat extends Component <TextChatPropsType, TextChatStateType> {
      private scrollTarget = React.createRef<HTMLDivElement>();
      componentDidMount() {
        this.scrollToBottom();//scroll to bottom on mount
      }
    
      componentDidUpdate() {
        this.scrollToBottom();//scroll to bottom when new message was added
      }
    
      scrollToBottom = () => {
        const node: HTMLDivElement | null = this.scrollTarget.current; //get the element via ref
    
        if (node) { //current ref can be null, so we have to check
            node.scrollIntoView({behavior: 'smooth'}); //scroll to the targeted element
        }
      };
    
      render <div>
        {message.map((m: Message) => <ChatMessage key={`chat--${m.id}`} message={m}/>}
         <div ref={this.scrollTarget} data-explanation="This is where we scroll to"></div>
       </div>
    }
    

    For more information about using ref with React and Typescript you can find a great article here.

    0 讨论(0)
提交回复
热议问题