我想建立一个聊天系统,并自动滚动到底部时,进入窗口,当新的消息进来。如何在React中自动滚动到容器底部?


当前回答

如果你想用React Hooks做到这一点,可以遵循这个方法。对于一个虚拟div已放置在聊天的底部。这里使用useRef Hook。

Hooks API参考: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>
  );
}

其他回答

我在mweb/web中遇到过这个问题。所有的解决方案是很好的在这个页面,但所有的解决方案是不工作,而使用android chrome浏览器。 所以对于mweb和web,我得到了一些小的解决方案。

    import { createRef, useEffect } from 'react';
    import { useSelector } from 'react-redux';
    import { AppState } from 'redux/store';
    import Message from '../Message/Message';
    import styles from './MessageList.module.scss';
    
    const MessageList = () => {
      const messagesEndRef: any = createRef();
      const { messages } = useSelector((state: AppState) => state?.video);
      const scrollToBottom = () => {
          //this is not working in mWeb
            // messagesEndRef.current.scrollIntoView({
            //   behavior: 'smooth',
            //   block: 'end',
            //   inline: 'nearest',
            // });
         const scroll =
          messagesEndRef.current.scrollHeight -
           messagesEndRef.current.clientHeight;
         messagesEndRef.current.scrollTo(0, scroll);
      };
    
      useEffect(() => {
        if (messages.length > 3) {
          scrollToBottom();
        }
      }, [messages]);
    
      return (
        <section className={styles.footerTopSection} ref={messagesEndRef} >
          {messages?.map((message: any) => (
            <Message  key={message.id} {...message} />
          ))}
        </section>
      );
    };
    
    export default MessageList;

我在消息的末尾创建了一个空元素,并滚动到该元素。不需要跟踪裁判。

不使用findDOMNode

带有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; }} />
  }
}

带钩子的功能组件:

import React, { useRef, useEffect } from 'react';

const MyComponent = () => {
  const divRef = useRef(null);

  useEffect(() => {
    divRef.current.scrollIntoView({ behavior: 'smooth' });
  });

  return <div ref={divRef} />;
}

如果用户已经在可滚动部分的底部,react- scrolable -feed会自动向下滚动到最新的元素。否则,它将使用户处于相同的位置。我认为这对聊天组件非常有用:)

我认为这里的其他答案将强制每次滚动,无论滚动条在哪里。scrollIntoView的另一个问题是,如果您的可滚动div不在视图中,它将滚动整个页面。

它可以这样使用:

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>
    );
  }
}

只要确保包装器组件具有特定的高度或max-height即可

免责声明:我是包裹的所有者

工作的例子:

您可以使用DOM scrollIntoView方法使组件在视图中可见。

为此,在呈现组件时,只需使用ref属性为DOM元素提供一个引用ID。然后在componentDidMount生命周期上使用scrollIntoView方法。我只是把这个解决方案的工作示例代码。以下是每次接收到消息时的组件呈现。您应该编写代码/方法来呈现该组件。

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>
        );
    }
}

这里this.props.message.MessageId是作为道具传递的特定聊天消息的唯一ID