Home  >  Q&A  >  body text

Firestore client in React app doesn't use Websockets but makes hundreds of POST requests

I'm new to React and Firestore (version 9).

I followed the tutorial to create a simple listener to read and display the collection. I want Firestore to open Websocket by default and keep documents in sync through it. Turns out it's making multiple POST requests per second to endpoint https://firestore.googleapis.com/google.firestore.v1.Firestore/Listen/channel?VER=8&database=...

I'm not in a VPN, and my firewall shouldn't be blocking Websockets.

Should I be worried about such a large number of requests? Can I somehow force FS to use Websockets?

I read Firebase.INTERNAL.forceWebSockets(); but it doesn't seem to be accessible in Typescript.

My component:

export default function App() {
    const dogsCol = collection(firestore, 'dogs');

    const [dogs, setDogs] = React.useState<Dog[]>([]);

    useEffect(() => {
        const unSubscribe = onSnapshot(dogsCol, dogsSnap => {
            const dogsArray = dogsSnap.docs.map(dogSnap => {
                const dog = dogSnap.data() as Dog;
                dog.id = dogSnap.id;
                return dog;
            });
            setDogs(dogsArray);
        });

        return () => unSubscribe();
    });

    return (
        <Container maxWidth="sm">
            <Box sx={{ my: 4 }}>
                {dogs.map(dog => <div key={dog.id}>{dog.name}</div>)}
            </Box>
        </Container>
    );
}

My Firestore configuration:

const firebaseConfig = {
    apiKey: "...",
    //etc
};
const app = initializeApp(firebaseConfig);


export const auth = getAuth(app);
export const firestore = getFirestore(app);

const provider = new GoogleAuthProvider();
provider.setCustomParameters({
  prompt: 'select_account'
});

export const signInWithGoogle = () => signInWithPopup(auth, provider)

P粉006847750P粉006847750208 days ago433

reply all(1)I'll reply

  • P粉038856725

    P粉0388567252024-02-27 15:32:05

    question:

    The reason you are getting multiple post requests per second is because your useEffect does not have any dependencies array and

    (The highlighted part is changing your dog's state, which causes a re-render, thus calling the unsubscribe method, and after the re-render useEffect is entered again and an infinite loop appears)

    Adding an empty array should fix the problem (yes, you should worry about and avoid this as it may cause frontend and backend issues such as performance, freezes, crashes, and may also cause you to pay some Firestore bills).

    How to fix it:

    Try changing useEffect to

    useEffect(() => {
            const unSubscribe = onSnapshot(dogsCol, dogsSnap => {
                const dogsArray = dogsSnap.docs.map(dogSnap => {
                    const dog = dogSnap.data() as Dog;
                    dog.id = dogSnap.id;
                    return dog;
                });
                setDogs(dogsArray);
            });
    
            return () => unSubscribe();
        },[]); // <- this empty array will cause this to only execute the effect onMount

    If you set up the rest correctly, adding an empty dependency array (so you only subscribe when the component is installed) should keep your data in sync (no need for Firebase.INTERNAL.forceWebSockets(); or similar s things)

    reply
    0
  • Cancelreply