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

dwbf0jvd  于 2023-03-23  发布在  React
关注(0)|答案(1)|浏览(99)

我是新的React和Firestore(版本9)。
我按照教程创建了一个简单的侦听器,用于读取和显示集合。我希望Firestore默认打开WebSocket并通过它保持文档同步。结果,它每秒向端点https://firestore.googleapis.com/google.firestore.v1.Firestore/Listen/channel?VER=8&database=...发出几次POST请求
我不在VPN和我的防火墙不应该阻止websockets也。
我应该担心这么多的请求吗?我能以某种方式强制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)
92vpleto

92vpleto1#

发行日期:

你每秒收到几次post请求的原因是因为你的useEffect没有得到任何依赖数组
您可以使用onSnapshot()方法监听文档。使用您提供的回调进行初始调用时,会立即使用单个文档的当前内容创建一个文档快照。然后,每当内容发生更改时,另一个调用会更新文档快照。
(the突出显示的部分正在更改您的狗的状态,这将导致重新渲染,这将调用unsubscribe方法,重新渲染后,将再次输入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();或类似的东西)

相关问题