0

I am a little lost on how to create infinite scroll elements in next.js with firebase firestore.

I am trying to use "my api" and use firestore on my api files.

My call to api is like this for now. I have a list called data, I send a request to my api and get the first 9 (limit param) docs.

useEffect(() => {
  console.log("useEffect");
  const getImage = async () => {
    const req = await fetch(`api/firebase?limit=9`, {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
      },
    });
    const data = await req.json();
    return data;
  };
  getImage().then((data) => {
    setData(data);
  });
}, []);

And my request handling is like this:

if (req.method === "GET") {
  const qu = req.query;
  const max = qu.limit;
  const q = query(collection(db, "images"), limit(max));
  const querySnapshot = await getDocs(q);
  const data = querySnapshot.docs.map((doc) => {
    return {
      label: doc.data().label,
      url: doc.data().url,
      id: doc.id,
    };
  });
  res.status(200).json(data);
}

I have tried/ looked up to react-infinite-scroll-component and I think I can make it work but I am lost on how to get the next 9 docs with my api from firebase.

On firestore there's startAfter() which takes documentSnapshot not an id but I can work with that by saving the id from the last doc send and calling it with getDoc with that id and start after that, but I don't know how to implement that thought with my api calling. Let's say there are 27 docs on my firestore, I call that first 9 with useEffect, do I need another function to call and update my data? I could try sending the last id as param and update but that gets complicated and I don't know if there's a simple way to this.

Saeed Zhiany
  • 2,051
  • 9
  • 30
  • 41
W33baker
  • 61
  • 8
  • 1
    Here you have examples how you can make paginated calls to Firebase. Including my one, but not for API. https://stackoverflow.com/questions/61572573/whats-the-best-way-to-paginate-and-filters-large-set-of-data-in-firebase – Mises Jul 23 '22 at 04:28

2 Answers2

1

Reviewing how infinite scroll works, generally you’d have two separate queries:

  1. Query for the first batch (without the startAfter)
  2. Query for loading more content (exact same query, but with startAfter())

You can actually review this quick guide for infinite scrolling with Firebase.

Now, with the situation you are having with your API, in the absence of any set order, the document ID serves as the sort order. In this case, you can simply use a where clause to retrieve all documents with an ID greater than or lower than the one you specify.

For example: where(FieldPath.documentId(), ">", id).

0

If anyone else stumble upon such problem here's how i solved it

I added this if statement to my api handler which checks if i sent docID param via call and gets the document with that id, after that i sent that document to startAfter.

if (qu.docID) {
  const id = qu.docID;
  const max = qu.limit;

  const idquery = query(
    collection(db, "images"),
    where("__name__", "==", id)
  );

  const documentSnapshots = await getDocs(idquery);
  const lastVisible =
    documentSnapshots.docs[documentSnapshots.docs.length - 1];

  const next = query(
    collection(db, "images"),
    orderBy("createdAt", "desc"),
    startAfter(lastVisible),
    limit(max)
  );
  const querySnapshot = await getDocs(next);
  const data = querySnapshot.docs.map((doc) => {
    return {
      label: doc.data().label,
      url: doc.data().url,
      id: doc.id,
    };
  });
  res.status(200).json(data);
}

Like Jose German said i created another function for loading more

const getNext = async (docID) => {
console.log("getNext");
const req = await fetch(`api/firebase?limit=9&docID=${docID}`, {
  method: "GET",
  headers: {
    "Content-Type": "application/json",
  },
});

const data = await req.json();
return data;
};

Lasly i used react-infinite-scroll-component's next={} to call my second function and after few tweaks it worked

W33baker
  • 61
  • 8