Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何在react中滚动到底部?_Reactjs - Fatal编程技术网

Reactjs 如何在react中滚动到底部?

Reactjs 如何在react中滚动到底部?,reactjs,Reactjs,我想建立一个聊天系统,并在进入窗口和收到新消息时自动滚动到底部。如何在React中自动滚动到容器底部?您可以使用refs跟踪组件 如果您知道设置单个组件(最后一个)的ref,请发布 以下是我发现对我有用的东西: class ChatContainer extends React.Component { render() { const { messages } = this.props; var messageBubbles = messages.map

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

您可以使用
ref
s跟踪组件

如果您知道设置单个组件(最后一个)的
ref
,请发布

以下是我发现对我有用的东西:

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();
    }
  }
}
类ChatContainer扩展React.Component{
render(){
常数{
信息
}=这是道具;
var messageBubbles=messages.map((message,idx)=>(
这个[''u div'+idx]=ref}
/>
));
返回(
{messageBubbles}
);
}
componentDidMount(){
这个.handleResize();
//初始化时滚动至底部
var len=this.props.messages.length-1;
const node=ReactDOM.findDOMNode(这个[''u div'+len]);
如果(节点){
scrollIntoView();
}
}
componentDidUpdate(){
//当新元素出现时滚动
var len=this.props.messages.length-1;
const node=ReactDOM.findDOMNode(这个[''u div'+len]);
如果(节点){
scrollIntoView();
}
}
}

我在消息末尾创建了一个空元素,并滚动到该元素。无需跟踪引用。

正如Tushar提到的,您可以在聊天的底部保留一个虚拟div:

render(){
返回(
{this.renderMessages()}
{this.messagesEnd=el;}}>
);
}
然后在组件更新时滚动到它(即添加新消息时状态更新):

scrollToBottom=()=>{
this.messagesEnd.scrollIntoView({behavior:“smooth”});
}
componentDidMount(){
这个.scrollToBottom();
}
componentDidUpdate(){
这个.scrollToBottom();
}
我在这里使用的是标准方法。

多亏了@enlitement

我们应该避免使用
findDOMNode
, 我们可以使用
refs
来跟踪组件

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();
}
render(){
...
返回(
{
this.messageList=div;
}}
>
{messageListContent}
);
}
scrollToBottom(){
const scrollHeight=this.messageList.scrollHeight;
const height=this.messageList.clientHeight;
const maxScrollTop=滚动高度-高度;
this.messageList.scrollTop=maxScrollTop>0?maxScrollTop:0;
}
componentDidUpdate(){
这个.scrollToBottom();
}
参考:

  • 引用您的邮件容器

    <div ref={(el) => { this.messagesContainer = el; }}> YOUR MESSAGES </div>
    
  • componentDidMount
    componentDidUpdate
    上调用上述方法

    componentDidMount() {
         this.scrollToBottom();
    }
    
    componentDidUpdate() {
         this.scrollToBottom();
    }
    
  • 这是我在代码中使用的方式:

     export default class StoryView extends Component {
    
        constructor(props) {
            super(props);
            this.scrollToBottom = this.scrollToBottom.bind(this);
        }
    
        scrollToBottom = () => {
            const messagesContainer = ReactDOM.findDOMNode(this.messagesContainer);
            messagesContainer.scrollTop = messagesContainer.scrollHeight;
        };
    
        componentDidMount() {
            this.scrollToBottom();
        }
    
        componentDidUpdate() {
            this.scrollToBottom();
        }
    
        render() {
            return (
                <div>
                    <Grid className="storyView">
                        <Row>
                            <div className="codeView">
                                <Col md={8} mdOffset={2}>
                                    <div ref={(el) => { this.messagesContainer = el; }} 
                                         className="chat">
                                        {
                                            this.props.messages.map(function (message, i) {
                                                return (
                                                    <div key={i}>
                                                        <div className="bubble" >
                                                            {message.body}
                                                        </div>
                                                    </div>
                                                );
                                            }, this)
                                        }
                                    </div>
                                </Col>
                            </div>
                        </Row>
                    </Grid>
                </div>
            );
        }
    }
    
    导出默认类StoryView扩展组件{
    建造师(道具){
    超级(道具);
    this.scrolltobttom=this.scrolltobttom.bind(this);
    }
    scrollToBottom=()=>{
    const messagescocontainer=ReactDOM.findDOMNode(this.messagescocontainer);
    messagesContainer.scrollTop=messagesContainer.scrollHeight;
    };
    componentDidMount(){
    这个.scrollToBottom();
    }
    componentDidUpdate(){
    这个.scrollToBottom();
    }
    render(){
    返回(
    {this.messagescocontainer=el;}}
    className=“chat”>
    {
    this.props.messages.map(函数(message,i){
    返回(
    {message.body}
    );
    },本页)
    }
    );
    }
    }
    
    作为另一个选项,它值得一看组件。

    我喜欢用下面的方法

    componentDidUpdate(prevProps, prevState){
      this.scrollToBottom();
    }
    
    scrollToBottom() {
      const {thing} = this.refs;
      thing.scrollTop = thing.scrollHeight - thing.clientHeight;
    }
    
    render(){
      return(
        <div ref={`thing`}>
          <ManyThings things={}>
        </div>
      )
    }
    
    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>
            );
        }
    }
    
    componentDidUpdate(prevProps,prevState){
    这个.scrollToBottom();
    }
    scrollToBottom(){
    const{thing}=this.refs;
    thing.scrollTop=thing.scrollHeight-thing.clientHeight;
    }
    render(){
    返回(
    )
    }
    
    不要使用

    使用ref对组件进行分类
    类MyComponent扩展组件{
    componentDidMount(){
    这个.scrollToBottom();
    }
    componentDidUpdate(){
    这个.scrollToBottom();
    }
    scrollToBottom(){
    this.el.scrollIntoView({behavior:'smooth'});
    }
    render(){
    返回{this.el=el;}}/>
    }
    }
    
    带挂钩的功能组件:
    import React,{useRef,useffect}来自“React”;
    常量MyComponent=()=>{
    const divRref=useRef(null);
    useffect(()=>{
    divRef.current.scrollIntoView({behavior:'smooth'});
    });
    返回;
    }
    
    工作示例:

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

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

    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>
            );
        }
    }
    
    class-ChatMessage扩展组件{
    scrollToBottom=(参考)=>{
    this.refs[ref].scrollIntoView({behavior:“smooth”});
    }
    componentDidMount(){
    this.scrolltobttom(this.props.message.MessageId);
    }
    render(){
    返回(
    Messag
    
    import React, {Component} from 'react';
    
    export default class ChatOutPut extends Component {
    
        constructor(props) {
            super(props);
            this.state = {
                messages: props.chatmessages
            };
        }
        componentDidUpdate = (previousProps, previousState) => {
            if (this.refs.chatoutput != null) {
                this.refs.chatoutput.scrollTop = this.refs.chatoutput.scrollHeight;
            }
        }
        renderMessage(data) {
            return (
                <div key={data.key}>
                    {data.message}
                </div>
            );
        }
        render() {
            return (
                <div ref='chatoutput' className={classes.chatoutputcontainer}>
                    {this.state.messages.map(this.renderMessage, this)}
                </div>
            );
        }
    }
    
    class Messages extends React.Component {
    
      const messagesEndRef = React.createRef()
    
      componentDidMount () {
        this.scrollToBottom()
      }
      componentDidUpdate () {
        this.scrollToBottom()
      }
      scrollToBottom = () => {
        this.messagesEnd.current.scrollIntoView({ behavior: 'smooth' })
      }
      render () {
        const { messages } = this.props
        return (
          <div>
            {messages.map(message => <Message key={message.id} {...message} />)}
            <div ref={this.messagesEndRef} />
          </div>
        )
      }
    }
    
    import React, { useEffect, useRef } from 'react'
    
    const Messages = ({ messages }) => {
    
      const messagesEndRef = useRef(null)
    
      const scrollToBottom = () => {
        messagesEndRef.current?.scrollIntoView({ behavior: "smooth" })
      }
    
      useEffect(() => {
        scrollToBottom()
      }, [messages]);
    
      return (
        <div>
          {messages.map(message => <Message key={message.id} {...message} />)}
          <div ref={messagesEndRef} />
        </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>
        );
      }
    }
    
    scrollToBottom = () => {
       this.messagesEnd.scrollIntoView({ behavior: "smooth", block: "end", inline: "nearest" });
    }
    
    scrollToTop = () => {
       this.messagesEnd.scrollIntoView({ behavior: "smooth", block: "start", inline: "nearest" });
    }   
    
    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>
      );
    }
    
      window.scrollTo({
      top: document.body.scrollHeight,
      left: 0,
      behavior: 'smooth'
    });
    
        render()
            return(
                <body>
                    <div ref="messageList">
                        <div>Message 1</div>
                        <div>Message 2</div>
                        <div>Message 3</div>
                    </div>
                </body>
            )
        )
    
      scrollToBottom = () => {
        const { messageList } = this.refs;
        messageList.scrollIntoView({behavior: "smooth", block: "end", inline: "nearest"});
      }
    
    import { useEffect, useRef } from 'react'
    
    const messageRef = useRef();
    
    useEffect(() => {
        if (messageRef.current) {
          messageRef.current.scrollIntoView(
            {
              behavior: 'smooth',
              block: 'end',
              inline: 'nearest'
            })
        }
      })
    
    useEffect(() => {
      if (messageRef.current) {
        messageRef.current.scrollIntoView(
          {
            behavior: 'smooth',
            block: 'end',
            inline: 'nearest'
          })
      }
    },
    [stateVariable])
    
    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>
    )
    
    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>
                        )
            }
    }
    
    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>
    }
    
    import {useEffect, useRef} from "react";
    import React from "react";
    import styled from "styled-components";
    
    export interface Props {
        children: Array<any> | any,
    }
    
    export function AutoScrollList(props: Props) {
        const bottomRef: any = useRef();
    
        const scrollToBottom = () => {
            bottomRef.current.scrollIntoView({
                behavior: "smooth",
                block: "start",
            });
        };
    
        useEffect(() => {
            scrollToBottom()
        }, [props.children])
    
        return (
            <Container {...props}>
                <div key={'child'}>{props.children}</div>
                <div key={'dummy'} ref={bottomRef}/>
            </Container>
        );
    }
    
    const Container = styled.div``;
    
       scrollToBottom= async ()=>{
          document.getElementById('bottomID').scrollIntoView();
        }