我想构建一个聊天系统,并在进入窗口和收到新消息时自动滚动到底部。如何在React中自动滚动到容器的底部?
如何在反应中滚动到底部?
I like doing it the following way.
componentDidUpdate(prevProps, prevState){
this.scrollToBottom();
}
scrollToBottom() {
const {thing} = this.refs;
thing.scrollTop = thing.scrollHeight - thing.clientHeight;
}
render(){
return(
<div ref={`thing`}>
<ManyThings things={}>
</div>
)
}
As another option it is worth looking at react scroll component.
谢谢“ metakermit”的好答案,但是我认为我们可以做得更好一些,滚动到底部,我们应该使用以下代码:
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>
);
}
工作示例:
您可以使用DOM scrollIntoView
方法使组件在视图中可见。
为此,在渲染组件时,只需使用ref
属性为DOM元素提供参考ID 。然后使用方法scrollIntoView
上componentDidMount
的生命周期。我只是在为该解决方案提供一个有效的示例代码。以下是每次接收到消息时都会呈现的组件。您应该编写用于渲染此组件的代码/方法。
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
是作为传递的特定聊天消息的唯一IDprops
我在消息末尾创建了一个空元素,然后滚动到该元素。无需跟踪引用。
引用您的消息容器。
<div ref={(el) => { this.messagesContainer = el; }}> YOUR MESSAGES </div>
找到您的消息容器并将其
scrollTop
属性设为相等scrollHeight
:scrollToBottom = () => { const messagesContainer = ReactDOM.findDOMNode(this.messagesContainer); messagesContainer.scrollTop = messagesContainer.scrollHeight; };
在
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>
);
}
}
感谢@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();
}
参考:
正如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();
}
我在这里使用标准的Element.scrollIntoView方法。
The easiest and best way I would recommend is.
My ReactJS version: 16.12.0
HTML structure inside
render()
functionscrollToBottom()
function which will get reference of the element. and scroll according toscrollIntoView()
function.and call the above function inside
componentDidMount()
andcomponentDidUpdate()
for more explanation about
Element.scrollIntoView()
visit developer.mozilla.org