scrollIntoView 在第一次加载和每次刷新后不起作用
scrollIntoView does not work on first load and after each refresh
我在聊天中看到一个非常奇怪的行为。打开聊天后,只有当聊天中有图像时,滚动条才会向下移动一点点。当有只有text的时候,就一直往下走。此外,如果我关闭聊天并再次打开它,无论内容如何,滚动都会一直向下。但是,如果我刷新页面,滚动 returns 会出现奇怪的行为。我很困惑为什么会这样。这是我的代码:
聊天是这样开始的:
startChat () {
document.getElementById("myForm").style.display = "block";
const ref = firebase.firestore().collection('Chats').doc(this.state.uid).collection('Messages');
const query = ref.orderBy('timestamp', 'desc').limit(10)
this.unsubFromMessages = query.onSnapshot((snapshot) => {
if (snapshot.empty) {
console.log('No matching documents.');
firebase.firestore().collection('Chats').doc(this.state.uid).
set({
name: this.state.displayName,
uid: this.state.uid,
email: this.state.email
}).then(console.log("info saved"))
.catch((error) => {
console.log("Error saving info to document: ", error);
});
}
snapshot.docChanges().reverse().forEach((change) => {
if (change.type === 'removed') {
console.log(change.doc.data().content)
}
else if (change.type === 'added') {
this.setState(state => {
const messages = [...state.messages, {id: change.doc.id, body: change.doc.data()}]
return {
messages
}
})
setTimeout( this.scrollToBottom(), 2000)
}
else if (change.type === 'modified') {
const filteredMessages = this.state.messages.filter(message => message.body.allowed === "yes")
this.setState(state => {
const messages = [...filteredMessages, {id: change.doc.id, body: change.doc.data()}]
return {
messages
}
})
setTimeout( this.scrollToBottom(), 2000)
}
});
}, (error) => {console.log(error)});
}
这是滚动功能:
scrollToBottom = () => {
this.myRef.current.scrollIntoView({ behavior: "smooth" });
}
这是聊天的 JSX:
<div className="form-popup" id="myForm">
<form className="form-container" onSubmit={this.chatFormSubmit}>
<h1>Chat</h1>
<label htmlFor="msg"><b>Message</b></label>
<div className="chatArea" id='messages'>
{
this.state.messages.map((message, index) => {
return message.body.uid === this.state.uid && !message.body.imageUrl
?
<p className="message-sent" key={index}>{message.body.content}</p>
:
message.body.uid === this.state.uid && message.body.imageUrl
?
<img src={message.body.imageUrl} className="message-sent" key={index}></img>
:
<p className="message-received" key={index}>{message.body.content}</p>
})
}
<div style={{ float:"left", clear: "both" }}
ref={this.myRef}>
</div>
</div>
如果关闭和向聊天提交消息的功能有任何用处,它们是:
closeForm() {
document.getElementById("myForm").style.display = "none";
this.setState({messages: []})
this.unsubFromMessages();
}
chatFormSubmit(e) {
e.preventDefault();
this.setState({ writeError: null });
firebase.firestore()
.collection('Chats')
.doc(this.state.uid)
.collection('Messages')
.doc()
.set({
docId: this.state.docId,
content: this.chatArea.current.value,
allowed: "yes",
timestamp: new Date(),
uid: this.state.uid,
name: this.state.displayName,
email: this.state.email
}, { merge: true })
.catch((error) => {
this.setState({ writeError: error.message });
})
.then(this.chatArea.current.value = '')
}
再一次,我自己弄明白了。与其在 setTimeout 中调用“this.scrollToBottom()”,不如像这样简单地传递它 setTimeout( this.scrollToBottom, 2000)。这就是为什么 setTimeout 不起作用并且滚动中途停止的原因。感谢 Felix Kling 在 中的评论。
我在聊天中看到一个非常奇怪的行为。打开聊天后,只有当聊天中有图像时,滚动条才会向下移动一点点。当有只有text的时候,就一直往下走。此外,如果我关闭聊天并再次打开它,无论内容如何,滚动都会一直向下。但是,如果我刷新页面,滚动 returns 会出现奇怪的行为。我很困惑为什么会这样。这是我的代码:
聊天是这样开始的:
startChat () {
document.getElementById("myForm").style.display = "block";
const ref = firebase.firestore().collection('Chats').doc(this.state.uid).collection('Messages');
const query = ref.orderBy('timestamp', 'desc').limit(10)
this.unsubFromMessages = query.onSnapshot((snapshot) => {
if (snapshot.empty) {
console.log('No matching documents.');
firebase.firestore().collection('Chats').doc(this.state.uid).
set({
name: this.state.displayName,
uid: this.state.uid,
email: this.state.email
}).then(console.log("info saved"))
.catch((error) => {
console.log("Error saving info to document: ", error);
});
}
snapshot.docChanges().reverse().forEach((change) => {
if (change.type === 'removed') {
console.log(change.doc.data().content)
}
else if (change.type === 'added') {
this.setState(state => {
const messages = [...state.messages, {id: change.doc.id, body: change.doc.data()}]
return {
messages
}
})
setTimeout( this.scrollToBottom(), 2000)
}
else if (change.type === 'modified') {
const filteredMessages = this.state.messages.filter(message => message.body.allowed === "yes")
this.setState(state => {
const messages = [...filteredMessages, {id: change.doc.id, body: change.doc.data()}]
return {
messages
}
})
setTimeout( this.scrollToBottom(), 2000)
}
});
}, (error) => {console.log(error)});
}
这是滚动功能:
scrollToBottom = () => {
this.myRef.current.scrollIntoView({ behavior: "smooth" });
}
这是聊天的 JSX:
<div className="form-popup" id="myForm">
<form className="form-container" onSubmit={this.chatFormSubmit}>
<h1>Chat</h1>
<label htmlFor="msg"><b>Message</b></label>
<div className="chatArea" id='messages'>
{
this.state.messages.map((message, index) => {
return message.body.uid === this.state.uid && !message.body.imageUrl
?
<p className="message-sent" key={index}>{message.body.content}</p>
:
message.body.uid === this.state.uid && message.body.imageUrl
?
<img src={message.body.imageUrl} className="message-sent" key={index}></img>
:
<p className="message-received" key={index}>{message.body.content}</p>
})
}
<div style={{ float:"left", clear: "both" }}
ref={this.myRef}>
</div>
</div>
如果关闭和向聊天提交消息的功能有任何用处,它们是:
closeForm() {
document.getElementById("myForm").style.display = "none";
this.setState({messages: []})
this.unsubFromMessages();
}
chatFormSubmit(e) {
e.preventDefault();
this.setState({ writeError: null });
firebase.firestore()
.collection('Chats')
.doc(this.state.uid)
.collection('Messages')
.doc()
.set({
docId: this.state.docId,
content: this.chatArea.current.value,
allowed: "yes",
timestamp: new Date(),
uid: this.state.uid,
name: this.state.displayName,
email: this.state.email
}, { merge: true })
.catch((error) => {
this.setState({ writeError: error.message });
})
.then(this.chatArea.current.value = '')
}
再一次,我自己弄明白了。与其在 setTimeout 中调用“this.scrollToBottom()”,不如像这样简单地传递它 setTimeout( this.scrollToBottom, 2000)。这就是为什么 setTimeout 不起作用并且滚动中途停止的原因。感谢 Felix Kling 在