首页 > 解决方案 > React + Firestore - 双向分页(按特定顺序查询新文档)

问题描述

介绍

我正在实现一个下拉刷新系统,在刷新时,我会获取新的用户帖子。

因此,我在 UI 中呈现这样的文档数据(按时间戳排序,降序排列):

当我在 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)某些文档可能会被跳过。

有什么帮助吗?

标签: javascriptreactjsfirebasegoogle-cloud-firestorenosql

解决方案


推荐阅读