我的应用程序中有一个无限滚动的项目表。表格呈现后,我订阅了前 20 项。这是我的监听器中的查询:
const firestoreQuery = query(
collectionGroup(firestore, 'items'),
orderBy('createdAt', 'desc'),
startAfter(Timestamp.fromDate(new Date(startValue))), // startValue is now() + 1min to ensure no items are skipped
limit(20));
我的想法是存储最后一个(第 20 个)项目的
createdAt
属性。这样,一旦用户在初始批次中滚动一点,我就会再次调用查询并发送不同的startValue
。
给定的 orderBy 语句是按降序创建的:
第一次调用(页面加载时):startValue = now() + 1min 以确保没有跳过任何项目
第二次调用(在表格滚动上): startValue = (第 20 项).createdAt
第三次调用(在表格滚动上): startValue = (第 40 项).createdAt
问题是,在第一个(页面加载)查询后 2 分钟创建的项目将不会被返回,因为它实际上已被 startValue 跳过。如果我在第一次(页面加载)调用中根本不传递 startValue,则由于 limit(20) 语句,它也可能不会被返回 => 初始调用可能返回 20 个项目和新创建的一个本来是 21 日,因此被排除在外。
我该如何解决这个问题?
我的想法是存储最后一个(第 20 个)项目的createdAt 属性。
您不应该存储文档字段数据来确定下一页,而是应该存储上次查看的文档的整个快照,并将该快照提供给
startAfter
。 这在文档中进行了讨论。 如果执行此操作,您将不会错过任何文档,假设将成为查询一部分的任何新文档都在查询末尾排序。 如果您对createdAt使用时间戳,这不会成为问题。