javascript - React + Firestore - 双向分页(按特定顺序查询新文档)
问题描述
介绍
我正在实现一个下拉刷新系统,在刷新时,我会获取新的用户帖子。
因此,我在 UI 中呈现这样的文档数据(按时间戳排序,降序排列):
第一次渲染(未刷新)
Post 4 - Timestamp: 9999 <--- Most recent post Post 3 - Timestamp: 9998 Post 2 - Timestamp: 9997 Post 1 - Timestamp: 9996 <--- Oldest post
第二次渲染(刷新后)
Post 6 - Timestamp 10001 <--- Most recent post Post 5 - Timestamp 10000 /* ====== OLD DATA ====== */ Post 4 - Timestamp: 9999 Post 3 - Timestamp: 9998 Post 2 - Timestamp: 9997 Post 1 - Timestamp: 9996 <--- Oldest post
当我在 FlatList 中呈现数据时,我为用户提供了一种在他/她滚动到列表底部(到达末尾)时“获取更多旧用户帖子”的方法。
查询代码
这是我当前对 api 方法的实现(我在其中执行查询):
export async function getUserPosts(
userId,
getOldPosts = true,
startAfter,
limit = MAX_USER_POSTS_TO_RETRIEVE
) {
const userPostsRef = firestore
.collection("posts")
.doc(userId)
.collection("userPosts");
const query = userPostsRef
.orderBy("date", getOldPosts ? "desc" : "asc")
.startAfter(startAfter);
const querySnapshot = await query.limit(limit).get();
const posts = querySnapshot.docs.map((doc) => parsePost(doc));
// Does the user have more posts to load?
const hasMoreToLoad = querySnapshot.size === limit;
// Calculate the new startAfter
if (querySnapshot.size) {
startAfter =
querySnapshot.docs[getOldPosts ? querySnapshot.docs.length - 1 : 0];
}
return { posts, hasMoreToLoad, startAfter };
}
我如何使用它
基本上,为了实现双向分页,我使用了两个游标:
export default function useFetchUserPosts(userId) {
const [posts, setPosts] = useState([]);
...
const newestPostCursor = useRef(new Date());
const oldestPostCursor = useRef(new Date());
...
}
newestPostCursor
用于startAfter
查询更多新帖子,oldestPostCursor
使用方式相同但方向相反。
这就是我调用我的 api 方法以获取用户最近的帖子的方式:
export default function useFetchUserPosts(userId) {
const [posts, setPosts] = useState([]);
...
const newestPostCursor = useRef(new Date());
const oldestPostCursor = useRef(new Date());
...
const getMoreNewPosts = async (limit) => {
if (isFetching.current) return;
isFetching.current = true;
try {
const { posts: newPosts, startAfter: newStartAfter } = await getUserPosts(
userId,
false,
newestPostCursor.current,
limit
);
newestPostCursor.current = newStartAfter;
if (newPosts.length) {
setPosts((prevPosts) => [...newPosts, ...prevPosts]);
}
isFetching.current = false;
} catch (err) {
// TODO - Show error in a toast
console.log(err);
}
};
...
}
旧帖子也是如此,但使用另一个光标。
问题
按照我想要的顺序正确检索旧帖子......
但是,新帖子(用于刷新)被检索为:
[Post 5, Post 6]
而不是
[Post 6, Post 5]
查询工作正常,它返回我想要的文档,但不是按照我需要的顺序...我知道我可以在客户端反转列表,但是是否可以在不更改的情况下按该顺序获取文档前端的顺序?
我认为问题出在startAfter
...也许我应该尝试使用endAt(newestPostCursor)
但是...我找不到正确的方法,因为 latestPostCursor 的初始值是 new Date()... 所以,在第一次刷新时,由于.limit(N)
某些文档可能会被跳过。
有什么帮助吗?
解决方案
推荐阅读
- c# - .Net Framework 4.8 MVC - ${aspnet-TraceIdentifier} 始终为空
- python - 使用 Selenium 时出错:DevToolsActivePort 文件不存在
- swift - 为什么我的 SwiftUI 列表样式偏离中心且背景为灰色?
- interbase - 无法在运行时使用带参数的查询创建用户
- java - 使用httpclient时如何覆盖方法?还需要什么?
- r - 如何在 R 中自定义 ggplot 图的轴?
- python - 有没有办法增加 sys.stdin 在 python 上接受的字符数?
- azure - 如何让内部 VM 解析 DNS 别名记录集中的主机名
- python - 基于自定义层次结构对 pandas 数据帧进行排序和提取
- javascript - 尝试遍历图像数组,但代码仅显示数字 1(甚至不显示数字 0)