我建立了一个聊天室。我希望在组件加载时或收到新消息时可以滚动到底部。没有React,我尝试了,它就起作用了。使用React,我不会成功。
感谢帮助
我已经在JavaScript中尝试过并且可以正常工作,我已经在带有ref的React中进行过尝试,例如JavaScript中的代码。
const contentMsgElement = document.querySelector("#contentMsg");
contentMsgElement.scrollTop = contentMsgElement.scrollHeight;
import React from 'react';
import ReactDOM from 'react-dom';
import MessageChat from './message/messageChat';
import moment from 'moment';
import MessageDateHeader from './message/messageDateHeader';
class BodyChat extends React.Component
{
constructor(props)
{
super(props);
this.state = {
socket:null,
allMessages:[],
dateNow:""
};
this.messageList = React.createRef();
}
componentDidMount()
{
const {socket,user} = this.props;
this.setState({
socket:socket,
user:user
},this.getLast10Msg);
this.setState({
dateNow:moment.utc().local().format("DD/MM/YY")
});
this.getNewMsg(socket);
}
componentDidUpdate(prevProps,prevState)
{
const prevAll = prevState.allMessages;
const all = this.state.allMessages
if(prevAll.length !== all.length)
{
if(this.messageList.current)
{
const messageList = this.messageList.current;
ReactDOM.findDOMNode(messageList).scrollTop = messageList.scrollHeight;
console.dir(ReactDOM.findDOMNode(messageList));
}
}
}
getLast10Msg = () =>
{
const {socket} = this.state;
socket.on("respGet10Msg",data =>
{
this.setState({
allMessages:data
});
});
}
getNewMsg = socket =>
{
socket.on("respMsg",data =>
{
const newMsg = {
userName:data.userName,
MESSAGE:data.message,
CODE_UTILISATEUR:data.userId,
TIME:data.time,
ID:(data.idMessage) ? "msg_" + data.idMessage : "tpm_" + data.idTpm
};
this.setState({
allMessages:this.state.allMessages.concat(newMsg)
});
this.scrollToBottom();
});
}
scrollToBottom = () =>
{
const contentMsg = this.messageList;
console.log(contentMsg);
contentMsg.scrollTop = contentMsg.scrollHeight;
}
msgDate = (time,displayDate) =>
{
const {dateNow} = this.state;
const date = moment.utc(time).local().format("DD/MM/YY");
const yesterday = moment.utc().local().subtract(1, 'days').format("DD/MM/YY");
const currentDate = displayDate.date;
const respDate = {...displayDate};
if(date !== currentDate)
{
if(dateNow === date)
{
respDate.date = "Aujourd'hui";
}
else if(yesterday === date)
{
respDate.date = "Hier";
}
else
{
respDate.date = date;
}
respDate.display = true;
}
else
{
respDate.display = false;
}
return respDate;
}
render()
{
const {allMessages,user} = this.state;
let displayDate = {date:"",display:false};
if(allMessages.length > 0)
{
const messages = allMessages.map(msg =>
{
const msgChat = <MessageChat
idMessage={msg.ID}
userName={msg.userName}
message={msg.MESSAGE}
userId={msg.CODE_UTILISATEUR}
time={msg.TIME}
currentUser={user.CODE_UTILISATEUR}
key={msg.ID}
/>;
displayDate = this.msgDate(msg.TIME,displayDate);
const msgDate = (displayDate.display) ? <MessageDateHeader date={displayDate.date}/> : "";
return <React.Fragment>
{msgDate}
{msgChat}
</React.Fragment>;
}
);
return <div className="contentMsg" ref={this.messageList}>
{messages}
{("Aujourd'hui" !== displayDate.date) ? <MessageDateHeader date="Aujourd'hui"/> : ""}
</div>;
}
else
{
return <div className="contentMsg">
</div>;
}
}
}
export default BodyChat;
.contentMsg
{
display: grid;
grid-gap: 0.2rem;
overflow-y: auto;
overflow-x: hidden;
}
除了滚动聊天或在底部更新时滚动之外,我没有滚动!
@anik伊斯兰教Shojib
我尝试不工作
componentDidUpdate(prevProps,prevState)
{
if(this.messageList)
{
console.log("here");
console.log(this.messageList.offsetTop);
window.scrollTo({
top:this.messageList.offsetTop,
behavior: "smooth" // Optional, adds animation
})
console.log(this.messageList.scrollTop);
}
}
答案 0 :(得分:1)
在聊天屏幕底部放置一个不可见 div
。 (在contentMsg
内部。)
<div style={{display: none}} />
然后,在构造函数中定义一个ref
:
this.myRef = React.createRef()
将此ref
附加到您不可见的div
:
<div style={{display: none}} ref={el => this.myRef = el} />
然后,每当您想滚动到底部(例如componentDidUpdate
)时,请调用此函数:
this.myRef.scrollIntoView();
答案 1 :(得分:1)
我找到了解决方案。我不知道为什么渲染没有完成,然后才调用函数componentDidUpdate。所以我们第一次说渲染器已经更新并且可以使用。
我认为这是一个技巧,但是如果有人知道更好的解决方案。
componentDidUpdate(prevProps,prevState)
{
if(this.state.allMessages.length > 0 && prevState.allMessages.length !== this.state.allMessages.length)
{
this.setState({ changeHeight: true });
}
if(this.state.changeHeight && this.state.changeHeight !== prevState.changeHeight)
{
let height = ReactDOM.findDOMNode(this).scrollHeight;
ReactDOM.findDOMNode(this).scrollTop = height;
this.setState({ changeHeight: false });
}
}
答案 2 :(得分:0)
这里是react的滚动代码。该代码对我来说也适用
componentDidUpdate(prevProps,prevState)
{
const prevAll = prevState.allMessages;
const all = this.state.allMessages
if(prevAll.length !== all.length)
{
if(this.messageList.current)
{
window.scrollTo({
top:this.messageList.offsetTop,
behavior: "smooth" // Optional, adds animation
})
console.dir(ReactDOM.findDOMNode(messageList));
}
}
}
您可以像
一样使用ref return <div className="contentMsg" ref={(e) => this.messageList= e} >
{messages}
{("Aujourd'hui" !== displayDate.date) ? <MessageDateHeader
date="Aujourd'hui"/> : ""}
</div>;
这也应该起作用,但对我也不起作用
ReactDOM.findDOMNode(messageList).scrollTop = messageList.scrollHeight;
您能尝试一件事吗?只能在componentDidUpdate的以下部分中运行
componentDidUpdate(prevProps,prevState)
{
window.scrollTo({
top:this.messageList.offsetTop,
behavior: "smooth" // Optional, adds animation
})
}
看看它是否有效,如果它起作用,则说明您的状况有问题