Firestore client in React app doesn't use Websockets but makes hundreds of POST requests
P粉006847750
P粉006847750 2024-02-26 16:56:12
0
1
502

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粉006847750
P粉006847750

reply all(1)
P粉038856725

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). p>

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();
    },[]); // 

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)

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template