How to scroll to bottom in react?

前端 未结 19 783
执笔经年
执笔经年 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:47

    thank you 'metakermit' for his good answer, but I think we can make it a bit better, for scroll to bottom, we should use this:

    scrollToBottom = () => {
       this.messagesEnd.scrollIntoView({ behavior: "smooth", block: "end", inline: "nearest" });
    }
    

    but if you want to scroll top, you should use this:

    scrollToTop = () => {
       this.messagesEnd.scrollIntoView({ behavior: "smooth", block: "start", inline: "nearest" });
    }   
    

    and this codes are common:

    componentDidMount() {
      this.scrollToBottom();
    }
    
    componentDidUpdate() {
      this.scrollToBottom();
    }
    
    
    render () {
      return (
        <div>
          <div className="MessageContainer" >
            <div className="MessagesList">
              {this.renderMessages()}
            </div>
            <div style={{ float:"left", clear: "both" }}
                 ref={(el) => { this.messagesEnd = el; }}>
            </div>
          </div>
        </div>
      );
    }
    
    0 讨论(0)
  • 2020-11-28 18:49

    The easiest and best way I would recommend is.

    My ReactJS version: 16.12.0


    For Class Components

    HTML structure inside render() function

        render()
            return(
                <body>
                    <div ref="messageList">
                        <div>Message 1</div>
                        <div>Message 2</div>
                        <div>Message 3</div>
                    </div>
                </body>
            )
        )
    

    scrollToBottom() function which will get reference of the element. and scroll according to scrollIntoView() function.

      scrollToBottom = () => {
        const { messageList } = this.refs;
        messageList.scrollIntoView({behavior: "smooth", block: "end", inline: "nearest"});
      }
    

    and call the above function inside componentDidMount() and componentDidUpdate()


    For Functional Components (Hooks)

    Import useRef() and useEffect()

    import { useEffect, useRef } from 'react'
    

    Inside your export function, (same as calling a useState())

    const messageRef = useRef();
    

    And let's assume you have to scroll when page load,

    useEffect(() => {
        if (messageRef.current) {
          messageRef.current.scrollIntoView(
            {
              behavior: 'smooth',
              block: 'end',
              inline: 'nearest'
            })
        }
      })
    

    OR if you want it to trigger once an action performed,

    useEffect(() => {
      if (messageRef.current) {
        messageRef.current.scrollIntoView(
          {
            behavior: 'smooth',
            block: 'end',
            inline: 'nearest'
          })
      }
    },
    [stateVariable])
    

    And Finally, to your HTML structure

    return(
        <body>
            <div ref={messageRef}> // <= The only different is we are calling a variable here
                <div>Message 1</div>
                <div>Message 2</div>
                <div>Message 3</div>
            </div>
        </body>
    )
    

    for more explanation about Element.scrollIntoView() visit developer.mozilla.org

    More detailed explanation in Callback refs visit reactjs.org

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

    Do not use findDOMNode

    Class components with ref

    class MyComponent extends Component {
      componentDidMount() {
        this.scrollToBottom();
      }
    
      componentDidUpdate() {
        this.scrollToBottom();
      }
    
      scrollToBottom() {
        this.el.scrollIntoView({ behavior: 'smooth' });
      }
    
      render() {
        return <div ref={el => { this.el = el; }} />
      }
    }
    

    Function components with hooks:

    import React, { useRef, useEffect } from 'react';
    
    const MyComponent = () => {
      const divRref = useRef(null);
    
      useEffect(() => {
        divRef.current.scrollIntoView({ behavior: 'smooth' });
      });
    
      return <div ref={divRef} />;
    }
    
    0 讨论(0)
  • 2020-11-28 18:51

    I could not get any of below answers to work but simple js did the trick for me:

      window.scrollTo({
      top: document.body.scrollHeight,
      left: 0,
      behavior: 'smooth'
    });
    
    0 讨论(0)
  • 2020-11-28 18:51

    Working Example:

    You can use the DOM scrollIntoView method to make a component visible in the view.

    For this, while rendering the component just give a reference ID for the DOM element using ref attribute. Then use the method scrollIntoView on componentDidMount life cycle. I am just putting a working sample code for this solution. The following is a component rendering each time a message received. You should write code/methods for rendering this component.

    class ChatMessage extends Component {
        scrollToBottom = (ref) => {
            this.refs[ref].scrollIntoView({ behavior: "smooth" });
        }
    
        componentDidMount() {
            this.scrollToBottom(this.props.message.MessageId);
        }
    
        render() {
            return(
                <div ref={this.props.message.MessageId}>
                    <div>Message content here...</div>
                </div>
            );
        }
    }
    

    Here this.props.message.MessageId is the unique ID of the particular chat message passed as props

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

    Using React.createRef()

    class MessageBox extends Component {
            constructor(props) {
                super(props)
                this.boxRef = React.createRef()
            }
    
            scrollToBottom = () => {
                this.boxRef.current.scrollTop = this.boxRef.current.scrollHeight
            }
    
            componentDidUpdate = () => {
                this.scrollToBottom()
            }
    
            render() {
                return (
                            <div ref={this.boxRef}></div>
                        )
            }
    }
    
    0 讨论(0)
提交回复
热议问题