首页  >  问答  >  正文

React 应用程序中的 Firestore 客户端不使用 Websockets,而是发出数百个 POST 请求

我是 React 和 Firestore 新手(版本 9)。

我按照教程创建了一个简单的侦听器来读取和显示集合。我希望 Firestore 默认打开 Websocket 并通过它保持文档同步。 事实证明,它每秒向端点 发出多次 POST 请求https://firestore.googleapis.com/google.firestore.v1.Firestore/Listen/channel?VER=8&database=...

我不在 VPN 中,我的防火墙也不应阻止 Websocket。

我应该担心如此大量的请求吗? 我可以以某种方式强制 FS 使用 Websockets 吗?

我读到了 Firebase.INTERNAL.forceWebSockets(); 但似乎无法在 Typescript 中访问。

我的组件:

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>
    );
}

我的 Firestore 配置:

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 天前434

全部回复(1)我来回复

  • P粉038856725

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

    问题:

    您每秒多次收到 post 请求的原因是因为您的 useEffect 没有任何依赖项数组并且

    (突出显示的部分正在更改您的狗的状态,这会导致重新渲染,从而调用取消订阅方法,并且在重新渲染后再次输入 useEffect 并出现无限循环)

    添加一个空数组应该可以解决该问题(是的,您应该担心并避免这种情况,因为它可能会导致前端和后端问题,例如性能、冻结、崩溃,并且还可能导致您需要支付一些 Firestore 账单)。

    如何修复它:

    尝试将 useEffect 更改为

    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

    如果您正确设置其余部分,添加空依赖项数组(因此仅在组件安装时订阅)应该使您的数据保持同步(不需要 Firebase.INTERNAL.forceWebSockets(); 或类似的东西)< /p>

    回复
    0
  • 取消回复