How to paginate Firestore data in react?

so I have been working on a web app similar to Instagram and I am trying to paginate the data(posts) from firestore, I tried the below code but on calling the function loadMorePosts it shows only the next two posts without retaining the previous new posts

Question 1: Why doesn’t it retain the previous new posts while setting the post in function loadMorePosts? I tried applying spread operator but it doesn’t help so

setPosts(...posts,
          snapShot.docs.map((doc) => ({ id: doc.id, post: doc.data() }))
        );

Question 2: Why snapShot.docs[snapShot.docs.length - 1] is an object, shouldn’t it be a number?

Question 3: How to know that there are no more post to fetch?

Code :

 const [posts, setPosts] = useState([]);
 const [latestDoc, setLatestDoc] = useState(null);

  const test = [];
  useEffect(() => {
    const unsub = db
      .collection("posts")
      .orderBy("timestamp", "desc")
      .limit(2)
      .onSnapshot((snapShot) => {
        setPosts(
          snapShot.docs.map((doc) => ({ id: doc.id, post: doc.data() }))
        );

    setLatestDoc(snapShot.docs[snapShot.docs.length - 1]);
      });

    return unsub;
  }, []);

  const loadMorePosts = async () => {
    db.collection("posts")
      .orderBy("timestamp", "desc")
      .startAfter(latestDoc)
      .limit(2)
      .onSnapshot((snapShot) => {
        setPosts(
          snapShot.docs.map((doc) => ({ id: doc.id, post: doc.data() }))
        );
        setLatestDoc(snapShot.docs[snapShot.docs.length - 1]);
      });
    console.log(test);
    console.log(latestDoc);
  };

Answer

Question 1: Why doesn’t it retain the previous new posts while setting the post in function loadMorePosts? Because post is an array, use have to do this:

setPosts([...posts,
      ...snapShot.docs.map((doc) => ({ id: doc.id, post: doc.data() }))
    ]);

Question 2: Why snapShot.docs[snapShot.docs.length – 1] is an object, shouldn’t it be a number?
It is obviously an object, how can it be a number?
It like:

snapShot.docs = [ {object 1}, {object 2}, {object 3} ]
snapShot.docs[snapShot.docs.length - 1] = snapShot.docs[2] = {object 3}

Question 3: How to know that there are no more post to fetch?

You could do something like this:

const [ hasMore, setHasMore ] = useState(false);
setHasMore(snapShot.docs.length > 0);

Leave a Reply

Your email address will not be published. Required fields are marked *