0

I'm currently trying to create a product page that displays all products and is a server component. The problem that I've run into is that I can't find a way to pass the last visible document snapshot required by the startAfter() query.

This is the function I'm using to get the documents:

export async function getProducts() {
  const q = query(
    collection(db, "products"),
    where("isHidden", "==", false),
    orderBy("createdAt", "desc"),
    limit(12)
  );

  const querySnapshot = await getDocs(q);
  const lastDoc = querySnapshot.docs[querySnapshot.docs.length - 1];
  const products = [];
  querySnapshot.forEach((doc) => {
    products.push({ ...doc.data(), id: doc.id });
  });
  return { products, lastDoc };
}

And this is the page itself:

export default async function ProductsBikiniPage({ searchParams }) {
  const page = searchParams["page"] ?? "1";

  const { products, lastDoc } = await getProducts();

  return (  
    <main>
      <section>
        //Listing products here
      </section>
      <section>
        <PaginationControls>
      </section>
    </main>
  );
}

The page params are there because at first I tried to paginate using pages but learned that firebase startAfter() needs a document snapshot to work (Can't just use .skip(12) for example). So yeah, I can't figure out a way to pass this lastDoc back to the getProducts function to get the next set of products without changing the component to a client component. Any ideas on how I can implement Firebase pagination in a Next server component would be appreciated.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

1 Answers1

0

The startAfter method actually has two overloads:

  • One variant takes a DocumentSnapshot as its parameter, and will start after that document.
  • The other variant takes a list of field values as its parameter, and is documented as:

fieldValues
unknown[]
The field values to start this query after, in order of the query's order by.

So based on these overloads you can:

  • either first load the document snapshot of the document to start after, for example based on its document ID - and then pass that snapshot to the first overload of startAfter.
  • or you can pass along all the field values that are involved in the conditions and order of the query, and pass those along to the second overload of startAfter.

The second approach has the advantange that it doesn't require an extra document load, but the first variant actually is a bit simpler to implement.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807