0

I am trying to make the changes in real time using nextjs and firebase firestore. However I do need to reload yet in order for me to see the changes.

const [getUsers, setUsers] = useState("");

const checkStatus = async (collectionName, valueFieldName, setterName) => {
    const q = query(
      collection(db, collectionName),
      where("isVerified", "==", valueFieldName)
    );
    const snapshot = await getCountFromServer(q);
    setterName(snapshot.data().count);
  };

and I am calling the function in the body using parameters

checkStatus("users", "false", setUsers);

and I am trying to display it by

<h1> user counter in realtime: {getUsers} </h1>
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

2 Answers2

1

I do need to reload yet in order for me to see the changes.

You need to listen to updates from Firebase Firestore to update the state in real-time without needing to reload the page. For that you should use onSnapshot which listens in real time which allows you to update your application's state and UI in real-time without needing to refresh the page.

Here’s one example:

import { collection, onSnapshot, query, where } from "firebase/firestore";
import { db } from "@/firebase/firebaseConfig";
import React, { useEffect, useState } from "react";

export default function snapshot() {
    const [userCount, setUserCount] = useState(0);

    const checkStatus = (
      collectionName: string,
      valueFieldName: boolean,
      setterName: React.Dispatch<React.SetStateAction<number>>
    ) => {
      const q = query(
        collection(db, collectionName),
        where("isVerified", "==", valueFieldName)
      );
      const unsubscribe = onSnapshot(q, (snapshot) => {
        const count = snapshot.size;
        setterName(count);
      });
      return unsubscribe;
    };
  
    useEffect(() => {
      const unsubscribe = checkStatus("users", false, setUserCount);
      return () => {
        unsubscribe();
      };
    }, []);
  
    return (
      <div>
        <h1>User Count: {userCount}</h1>
      </div>
    );
}

If you don't need real-time updates of the count, you can use the getCountFromServer() method instead of the onSnapshot() method to retrieve the count once the component mounts. Example for that:

import { collection, getCountFromServer, query, where } from "firebase/firestore";
import { db } from "@/firebase/firebaseConfig";
import React, { useEffect, useState } from "react";

export default function Home() {
  const [userCount, setUserCount] = useState(0);

  const checkStatus = async (
    collectionName: string,
    valueFieldName: boolean,
    setterName: React.Dispatch<React.SetStateAction<number>>
  ) => {
    const q = query(
      collection(db, collectionName),
      where("isVerified", "==", valueFieldName)
    );
    const snapshot = await getCountFromServer(q);
    const count = snapshot.data().count;
    setterName(count);
  };

  useEffect(() => {
    checkStatus("users", false, setUserCount);
  }, []);

  return (
    <div>
      <h1>User Count: {userCount}</h1>
    </div>
  );
}

Reference taken from: Count documents in Firestore Collection, onSnapshot

Rohit Kharche
  • 2,541
  • 1
  • 2
  • 13
  • Hello, this works! One question, does this read every time the database? including a sudden refresh of the page or navigating through different pages? If that so, it will increments my read in the "read" firestore? Thank you. If the answer of it is yes, then I'll consider the second one. – flutternewbiee Mar 14 '23 at 02:41
  • 1
    @flutternewbiee [this answer](https://stackoverflow.com/a/74752846/20239914) could solve your query regarding reads while using `onSnapshot`. – Rohit Kharche Mar 14 '23 at 06:28
1

Firestore's COUNT() queries currently don't support realtime updates. From the documentation on its limitations:

  • count() aggregation queries are currently only supported via direct server response. Queries are served only by the Cloud Firestore backend, skipping the local cache and any buffered updates. This behavior is identical to operations performed inside Cloud Firestore transactions. You cannot currently use count() queries with real-time listeners and offline queries.

So you will indeed either have to reload the page, or set up some client-side refresh mechanism to get the latest value from the server.

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