我想建立一个聊天系统,并自动滚动到底部时,进入窗口,当新的消息进来。如何在React中自动滚动到容器底部?
当前回答
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>
);
}
}
其他回答
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>
);
}
}
正如Tushar提到的,你可以在聊天的底部保留一个虚拟div:
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>
);
}
然后当你的组件更新时(即随着新消息的添加而更新状态)滚动到它:
scrollToBottom = () => {
this.messagesEnd.scrollIntoView({ behavior: "smooth" });
}
componentDidMount() {
this.scrollToBottom();
}
componentDidUpdate() {
this.scrollToBottom();
}
我使用的是标准元素。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即可
免责声明:我是包裹的所有者
这是根据上面的答案修改的,以支持“children”而不是数据数组。
注意:样式化组件的使用对于解决方案并不重要。
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``;
推荐文章
- 如何配置历史记录?
- React钩子:从回调中访问最新状态
- React-Native:应用程序未注册错误
- ReactJS和公共文件夹中的图像
- React: 'Redirect'没有从' React -router-dom'中导出
- 如何在React中使用钩子强制组件重新渲染?
- React组件中使用TypeScript的默认属性值
- 反应钩子-正确的方式清除超时和间隔
- 在React.js中正确的img路径
- 在React.js中更新组件onScroll的样式
- onClick ReactJS调用多个函数
- 为什么React 16中的Fragments比容器div更好?
- 如何在ReactJS中验证嵌套对象的PropTypes ?
- 如何在ReactJS中从“外部”访问组件方法?
- 'React'指的是一个UMD全局,但当前文件是一个模块