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


当前回答

在上面的答案中,scrollIntoView(…)方法有两个主要问题:

it's semantically incorrect, as it causes the entire page to scroll if your parent element is scrolled outside the window boundaries. The browser literally scrolls anything it needs to in getting the element visible. in a functional component using useEffect(), you get unreliable results, at least in Chrome 96.0.4665.45. useEffect() gets called too soon on page reload and the scroll doesn't happen. Delaying scrollIntoView with setTimeout(..., 0) fixes it for page reload, but not first load in a fresh tab, at least for me. shrugs

这是我一直在使用的解决方案,它很可靠,而且更兼容旧的浏览器:

function Chat() {
   const chatParent = useRef<HTMLDivElement(null);

   useEffect(() => {
      const domNode = chatParent.current;
      if (domNode) {
         domNode.scrollTop = domNode.scrollHeight;
      }
   })
   return (
      <div ref={chatParent}>
         ...
      </div>
   )
}

其他回答

您可以使用引用来跟踪组件。

如果你知道如何设置单个组件的引用(最后一个),请发布!

以下是我发现对我有用的方法:

class ChatContainer extends React.Component {
  render() {
    const {
      messages
    } = this.props;

    var messageBubbles = messages.map((message, idx) => (
      <MessageBubble
        key={message.id}
        message={message.body}
        ref={(ref) => this['_div' + idx] = ref}
      />
    ));

    return (
      <div>
        {messageBubbles}
      </div>
    );
  }

  componentDidMount() {
    this.handleResize();

    // Scroll to the bottom on initialization
    var len = this.props.messages.length - 1;
    const node = ReactDOM.findDOMNode(this['_div' + len]);
    if (node) {
      node.scrollIntoView();
    }
  }

  componentDidUpdate() {
    // Scroll as new elements come along
    var len = this.props.messages.length - 1;
    const node = ReactDOM.findDOMNode(this['_div' + len]);
    if (node) {
      node.scrollIntoView();
    }
  }
}

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

完整版(Typescript):

import * as React from React 导出类DivWithScrollHere扩展React。组件<any, any> { loading:any = React.createRef(); componentDidMount () { this.loading.scrollIntoView(假); } 呈现(){ 回报( <div ref={e =>{这个。装载= e;}}> <LoadingTile /> </div> . txt ) } }

如果用户已经在可滚动部分的底部,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即可

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

我不能得到以下任何答案的工作,但简单的js为我做的伎俩:

  window.scrollTo({
  top: document.body.scrollHeight,
  left: 0,
  behavior: 'smooth'
});