reactjs - 如何使用 Firebase 同时进行分页和接收新消息?
问题描述
我正在使用 Firebase 在 ReactJS 中制作聊天应用程序。
一切正常,但我在尝试使用分页时遇到了一些麻烦
我已经研究过这个并且效果很好:使用 react-firebase-hooks 的分页问题是,一旦我发送/加载一条新消息,它就会重新加载整个数据并复制它。
useList
然后之后我尝试使用而不是切换到实时数据库useCollection
使用useList
它有点工作,但它用底部元素替换顶部元素,因此删除已加载的信息。所以不是附加列表,它只是调整引用。
我看到另一种方法用于两个单独的列表,一个用于旧消息,一个用于新消息。但这看起来不是最有效的解决方案......
其他问题:[Accepted Answer] 使用两个单独的列表。
聊天.js
const users = [props.uid, auth.currentUser.uid]
users.sort()
const conversationReference = db.collection('conversations').doc(users[0] + "_" + users[1])
const queryFn = React.useCallback(() => {
let q = conversationReference
.collection('messages')
.orderBy('createdAt', 'desc')
.limit(20)
return q
}, [props.uid])
const [[messages, queryLoading, error], more] = useFirestoreLoadMore(queryFn)
const sendChat = () => {
if(message.length > 0) {
chatReference.add({
to: props.uid,
from: auth.currentUser.uid,
message: message,
createdAt: new Date(),
}).then((docRef) => {
conversationReference.update({
lastChat: message,
lastActivity: new Date()
}).then(() => {
setMessage('')
})
}).catch((error) => {
console.log("Error sending message")
})
}
}
useEffect(() => {
if(top && messages[messages.length - 1].data().message)
more()
}, [top])
messages[messages.length - 1].data().message
: 使用虚拟文档来表示收集结束
使用FirestoreLoadMore.js
import {useCollection, useCollectionData, useCollectionOnce} from 'react-firebase-hooks/firestore'
export const useFirestoreLoadMore = queryFn => {
const [query, setQuery] = useState(null)
const [last, setLast] = useState(null)
const [data, setData] = useState([])
const [qData, loading, error] = useCollection(query)
useEffect(() => {
setData([])
setQuery(queryFn())
}, [queryFn])
useEffect(() => {
if (qData && qData.query.isEqual(query)) {
setLast(qData.docs[qData.docs.length - 1])
//console.log("first: ", data.length, " | second: ", qData.docs.length)
setData([...data, ...qData.docs])
}
}, [qData])
const more = useCallback(() => {
setQuery(queryFn().startAfter(last))
}, [queryFn, setQuery, last])
return [[data, loading, error], more]
}
问题:我如何分页[messages]
ofuseList
或useCollection
(我对这两种方法都持开放态度。尚未完全确定哪一种最适合)同时还能接收新消息?
解决方案
我决定改变useFirestoreLoadMore
:
使用FirestoreLoadMore.js
export const useFirestoreLoadMore = queryFn => {
const baseValue = 20
const increment = 100
const [query, setQuery] = useState(null)
const [limit, setLimit] = useState(baseValue)
const [data, setData] = useState([])
const [qData, loading, error] = useCollection(query)
useEffect(() => {
setData([])
setQuery(queryFn().limit(limit))
}, [queryFn])
useEffect(() => {
if (qData && qData.query.isEqual(query)) {
setData([...qData.docs])
}
}, [qData])
const more = useCallback(() => {
setQuery(queryFn().limit(limit + increment))
setLimit(limit + increment)
}, [queryFn, setQuery])
return [[data, loading, error], more]
}
这不是我认为的最有效的方式。但是无论如何我都没有看到另一种保持实时更新的方法..
推荐阅读
- typescript - 如何让抽象类中的函数返回打字稿中子类的实例
- java - 使用 RxJava 进行分组移动平均
- r - Amazon S3 和 QGIS 之间的集成
- elasticsearch - 在 Elasticsearch 中实现基于限制的查询
- mips - 从字符串和打印 MIPS 中删除空格
- javascript - 将表单数据解析为 javascript 中的对象(无法读取未定义的属性“名称”)
- windows - 如何仅通过 LAN 在 Windows 上运行 docker-onlyoffice-nextcloud
- javascript - 如何在反应中使用 settimeout 方法?
- javascript - 使用 Jest 测试 Saga 生成器函数
- mariadb - 无法使用自制软件登录 mariadb