Search code examples
reactjsfirebasegoogle-cloud-firestorenext.jsreact-firebase-hooks

Reads rising exponentially using firestore in next.js


I have setup a page where it should open a collection and read all the data in it and then update the a document's data whenever a change happens in the document. However, i noticed that my reads are rising so much, it raised over a 2k~ reads for only 250 Docs when i only opened the page 3 times maybe. So max it should be 750 reads.

and no i don't have the console open, just usage panel

"use client";
import React, { useEffect, useState } from "react";
import { auth, db } from "@/app/firebase/config";
import { collection, doc, query, where } from "firebase/firestore";
import { useCollection, useDocumentOnce } from "react-firebase-hooks/firestore";
import { useSearchParams } from "next/navigation";
import clsx from "clsx";
import CardLoading from "./CardLoading";
import { useAuthContext } from "@/app/components/SessionProvider";

const GuestCard = ({ id }: { id: string }) => {
  const { session} = useAuthContext();
  const searchParams = useSearchParams();
  const searchItem = searchParams.get("query") || "";
  const guestRef = collection(db, `guests`);
  
  const [snapshot, eventloading, eventerror, reload] = useDocumentOnce(
    doc(db, `clients/${session?.uid}`)
  );

  const rejQ = query(
    guestRef,
    where("EventID", "==", `${id}${snapshot?.data()?.EventID}`)
  );
  const [value, loading, error] = useCollection(rejQ);
  const [filtered, setFiltered] = useState([]);
  useEffect(() => {
    if (value) {
      const filteredDocs = value.docs.filter((doc) => {
        const data = doc.data();
        return data.name.toLowerCase().includes(searchItem.toLowerCase());
      });
      setFiltered(filteredDocs as any);
    }
  }, [value, searchItem]);

  return (
    <div className="h-[56rem]">
      {loading && (
        <div>
          <CardLoading />
        </div>
      )}
      {error && <div>Error: {error.toString()}</div>}
      {filtered?.map((doc: any) => {
        const data = doc.data();
        return (
          <div key={doc.id} className="text-black">
            <div className="w-full rounded-md shadow p-2 px-4 my-2">
              <div className="flex flex-row justify-between">
                <div className="flex flex-col gap-1">
                  <p className="font-bold text-[#1C1C21]">{data.name}</p>
                  <div className="flex flex-col items-start gap-1 text-[#3D404A] text-sm font-light">
                    <div className="flex flex-row gap-1">
                      <p>Phone</p>
                      <p className="text-sm"> {data.number}</p>
                    </div>

                    <div className="flex flex-row gap-1">
                      <p className="text-sm text-[#3D404A]">Status</p>
                      <p>{data.status}</p>
                    </div>
                  </div>
                </div>

                <div className="pt-2  h-[2rem] flex justify-center items-center w-[5rem]">
                  <p
                    className={clsx(
                      "bg-[#74C365] rounded-lg p-1 px-2 font-light w-full flex justify-center",
                      {
                        "bg-[#74C365]": data.reply === "yes",
                        "bg-[#FF6961]": data.reply === "no",
                        "bg-[#FFC107]": data.status === "failed"
                      }
                    )}
                  >
                    {data.reply}
                  </p>
                </div>
              </div>
            </div>
          </div>
        );
      })}
    </div>
  );
};

export default GuestCard;

I tried opening the page once, and noticed the reads raising to around 700 (it's hard to get an exact number via the firebase usage analytics). I added a counter inside the useEffect, i noticed the count raises to the exact number of documents.

Sidenote- However, when i updated a document (via my own website that i use, its all writes so no reads from that website) the counter resets and goes from 1 to 250 again. So, maybe its not just chaning one document but reading all of them again?

Is there any better way to read the data realtime using next.js features? Because using firestore with with next feels like i just have to use 'use client' always and not rely on server sided actions


Solution

  • Solved

    My structure was {events/in-progress/[id]/page.tsx}

    inside the page.tsx i had the < GuestCard /> which was being re-rendered and everytime it was re-rendered the fetch was occuring. To solve this i took out all the firebase-hooks outside the GuestCard and placed the fetch inside the page.tsx and passed the data as value to the guest card

    Final structure looked like this < GuestCard data = {value} /> where value was the fetch data from firestore

    This solved my issue so now whatever filtering/searching inside the guestcard is being done on pre passed data from page.tsx so its not fetching every single reload