reactjs - 尝试获取用户的身份验证状态firebase时反应本机useEffect渲染问题
问题描述
我对 useEffect 有疑问。当我尝试在 之后获取用户的身份验证状态时,onAuthStateChanged
useEffect 中的调用次数非常高。有时它也会给出这个错误:
警告:无法对未安装的组件执行 React 状态更新。这是一个无操作,但表明您的应用程序中存在内存泄漏。要修复,请取消 useEffect 清理函数中的所有订阅和异步任务
这是用户登录/注册和注销后的日志量。也许我不太了解 useEffect 是如何工作的。这是使用 useEffect 的代码:
useEffect(async () => {
let isCancelled = false;
await firebase.auth().onAuthStateChanged(async (user) => {
if (user && !isCancelled) {
await firebase
.firestore()
.collection('users')
.doc(user.uid)
.get()
.then((document) => {
const userData = document.data()
console.log(document.data())
setUser(userData);
setIsSignedIn(true);
setLoading(false);
})
.catch((error) => {
setLoading(false);
alert(error)
});
}else{
console.log('user does not exist')
setIsSignedIn(false);
setLoading(false);
}
});
return () => {
isCancelled = true;
}
}, []);
解决方案
一般来说,每个人都useEffect
应该负责一项任务。此外,当前的使用方法isCancelled
实际上并没有像他们应该的那样清理听众。
对于反应,您应该尽可能使用实时更新。您还将受益于能够轻松分离侦听器。
这是您可以使用的脚手架。
// Set up a state variable to contain the user's info
// If a user is already logged in and validated, user is immediately
// set to their User object, otherwise show loading icon while we check
const [user, setUser] = useState(() => firebase.auth().currentUser || undefined);
const userLoading = user === undefined;
const isSignedIn = !!user;
// Set up a state variable to contain the user's data
const [userData, setUserData] = useState(undefined);
// Set up a state variable to contain whether this component is loading
const [loading, setLoading] = useState(true);
// effect to track user state and update `user` for any changes
// onAuthStateChanged returns its own cleanup function
useEffect(() => firebase.auth().onAuthStateChanged(setUser), []); // <- don't rerun
// effect to navigate to login
useEffect(() => {
if (user === null) {
// user is signed out
navigation.navigate('login');
}
}, [user]); // <- rerun when user changes
useEffect(async () => {
if (!isSignedIn) return; // you could write this as `userLoading || !isSignedIn`, but it's redundant
return firebase.firestore()
.collection('users')
.doc(user.uid)
.onSnapshot({ // <- onSnapshot() returns its own cleanup function
next(docSnapshot) {
const userData = docSnapshot.data();
setUserData(userData);
},
error(err) {
console.error(err);
alert(err);
}
});
}, [user]); // <- rerun when user changes
作为一个学习项目,考虑将其制成Context
或创建您自己的useAuth
函数,您可以在其中提取用户数据、用户对象和加载状态。
推荐阅读
- javascript - Discord.js v12 如何让命令只在特定服务器上运行?
- android - 如何安装Android Studio 4.0版
- c# - 为什么 linq Select 请求工作这么长时间?。网
- python - astype('float') 改变数据,而不仅仅是数据类型
- java - 如何在 WAR 文件中包含标签库以确保它可以在没有互联网访问的机器上运行?
- python - 在 python 3.6 上编写一个不和谐的欢迎命令(discord.py)
- vba - VBA 宏中的 Rest API
- uwp-xaml - CanvasVirtualControl InvalidateRegions 自动拆分,为什么?
- java - canvas.drawBitmap 致命错误 api 29 android
- java - 我们可以将所有功能保留在 android studio 的同一个类中吗?