使用 Firebase 停止无限循环



我第一次用钩子测试Firebase,遇到了众所周知的无限循环问题。

我知道还有许多其他问题可能接近这个问题,但我仍然无法在这种情况下解决这个问题。

这是应用程序上的代码.js:

import React, { useState, useEffect } from 'react';
import { auth, createUserProfileDocument } from './firebase/firebase.utils';
function App() {
const [user, setUser] = useState(null);
useEffect(() => {
auth.onAuthStateChanged(async userAuth => {
if (userAuth) {
const userRef = await createUserProfileDocument(userAuth);
userRef.onSnapshot(snapshot => {
setUser({
user: {
id: snapshot.id,
...snapshot.data()
}
})
});
console.log(user);
} else {
setUser(null);
}
});
}, [user]);
return (
<div></div>
);
}
export default App;

这里是 firebase.utils.js 的 createUserProfileDocument 函数:

export const createUserProfileDocument = async (userAuth, additionalData) => {
if (!userAuth) return;
const userRef = firestore.doc(`users/${userAuth.uid}`);
const snapshot = await userRef.get();
if (!snapshot.exists) {
const { displayName, email } = userAuth;
const createdAt = new Date();
try {
await userRef.set({
displayName,
email,
createdAt,
...additionalData
})
} catch (err) {
console.log('Error creating user', err.message);
}
}
return userRef;
};

在这种情况下,我将如何检查onAuthStateChanged是否确实发生了变化?我的印象是每次都会触发auth.onAuthStateChanged函数,生成无限循环。

以下是我检查的资源可能会有所帮助:

  • 中等

  • 堆栈溢出

提前谢谢你。

该方法onAuthStateChanged通过为用户的登录状态添加观察者来设置订阅。只需在组件挂载时订阅一次,在卸载组件时调用取消订阅,以防止观察器运行并导致内存泄漏。

为了回答为什么它会导致无限循环,您将user状态作为依赖项,这将导致观察者在每次更新状态值user时重新初始化,观察者将返回一个全新的userAuth对象并再次调用setUser它将更新用户状态,这将重新初始化观察器并一遍又一遍地重复相同的循环。

解决方案,

仅当组件装载时,通过将空数组作为依赖项传递给useEffect来设置订阅一次

function App() {
const [user, setUser] = useState(null);
useEffect(() => {
// auth.onAuthStateChanged will return a firebase.Unsubrcibe function
// which you can call to terminate the subscription
const unsubscribe = auth.onAuthStateChanged(async userAuth => {
if (userAuth) {
const userRef = await createUserProfileDocument(userAuth);
userRef.onSnapshot(snapshot => {
setUser({
user: {
id: snapshot.id,
...snapshot.data()
}
})
});
} else {
setUser(null);
}
});
// return a clean up function that will call unsubscribe to -
// terminate the subscription when component unmounts
return () => { unsubscribe() }
}, []); // important set an empty array as dependency
return (
<div></div>
);
}
export default App;

编辑 - 不要尝试将user变量记录在同一个useEffect钩子中,因为它需要一个空的依赖数组,而是使用另一个useEffect钩子来记录useruser作为依赖项传递的值。例

useEffect(() => {
console.log(user)
}, [user])

相关内容

  • 没有找到相关文章

最新更新