React Native中Firebase signOut()报Cannot read 'email' of null错误求助
问题解答
Firebase Auth的signOut()方法没有变化,依然是开箱即用,无需额外参数,调用后即可完成用户注销操作。你遇到的Cannot read 'email' of null错误,和signOut本身无关,是代码里的用户状态判断逻辑存在漏洞。
错误根源分析
在账户页面的getUser函数中,onAuthStateChanged的回调会在用户状态变化时触发(包括注销后):
- 用户注销后,回调里的
user参数会变成null,但你直接执行了let userEmail = user.email,此时访问null.email就会抛出错误。 - 你写的
user !== null || user !== undefined逻辑错误,应该用&&,而且这个判断没有包裹后续的危险代码,完全没起到保护作用。
修复方案
1. 修复账户页面的用户信息获取逻辑
修改getUser函数,先判断用户是否存在,再执行后续的Firestore查询,同时清理订阅避免内存泄漏:
const getUser = () => { // 保存订阅引用,用于组件卸载时清理 const unsubscribe = onAuthStateChanged(auth, (user) => { // 先判断user是否存在,不存在则重置本地状态 if (!user) { setUser({ first: "", last: "", email: "" }); return; } let userEmail = user.email; const docRef = doc(db, 'useraccounts', userEmail) getDoc(docRef) .then((docSnap) => { if (docSnap.exists()){ setUser(docSnap.data()); } else { console.log("用户文档不存在"); } }) .catch(err => console.error("获取用户信息失败:", err)); }); // 返回清理函数 return unsubscribe; } useEffect(() => { const unsubscribe = getUser(); // 组件卸载时取消订阅 return () => unsubscribe(); },[])
2. 完善AuthContext的注销逻辑
在handleSignOut中,除了清理AsyncStorage和userToken,还要重置userInfo状态,确保全局状态同步:
const handleSignOut = async () => { try { await signOut(auth); await AsyncStorage.removeItem('userToken'); await AsyncStorage.removeItem('userInfo'); setUserToken(null); setUserInfo(null); // 新增:重置用户信息状态 } catch (err) { console.error(`注销失败: ${err}`); } }
3. 移除AuthContext中的冗余逻辑
你在AuthContext里写了一段冗余的存储代码,会在组件每次渲染时执行,建议删除:
// 这段代码可以删除 if(userToken) { AsyncStorage.setItem('userToken', userToken); }
总结
- signOut()方法本身没有变化,你的用法是正确的。
- 错误的核心是没有处理用户注销后
user为null的情况,加上前置判断即可解决。 - 清理
onAuthStateChanged的订阅可以避免内存泄漏,完善全局状态重置能让应用状态更一致。
内容的提问来源于stack exchange,提问作者LOTUSMS
相关产品推荐
相关产品推荐

