我在退出应用程序时遇到了困难。我正在使用新安装的托管 Expo 应用程序以及 dev-client 和 @react-natice-firebase/auth,所有这些都处于当前版本。对于用户状态,我使用 Recoil。登录正常,退出时出现问题。这是我的 AuthProvider.ts
import React, { FC, Fragment, useEffect } from 'react';
import auth, { FirebaseAuthTypes } from '@react-native-firebase/auth';
import { useSetRecoilState } from 'recoil';
import { firebaseUser } from '../../../state/user/atoms/firebaseUser';
export const AuthProvider: FC = ({ children }) => {
const setUser = useSetRecoilState(firebaseUser);
const onAuthStateChanged = (user: FirebaseAuthTypes.User | null) => setUser(user);
useEffect(() => {
const subscriber = auth().onAuthStateChanged(onAuthStateChanged);
return subscriber;
}, []);
return <Fragment children={children} />;
};
还有我用来注销的功能:
const logout = () => async () => await auth().signOut()
<MainButton action={logout()} label={'Logout'} />
登录后,onAuthStateChanged监听器返回用户对象,但在点击“注销”按钮后,它会再次返回用户对象,而不是null,并且界面不会更新。再次点击后,控制台返回错误:
[未处理的承诺拒绝:错误:[auth/no-current-user] 当前没有用户登录。]
onAuthStateChanged 不再调用,用户状态保持不变,界面不更新。
重新启动应用程序后,用户状态将被清除,并且登录再次正常工作。切换用户时的行为类似(例如从匿名到登录)。
在 useEffect 中,您需要实际调用 useAuthStateChanged 提供的“取消订阅”函数。
useEffect(() => {
const unsubscribe = auth().onAuthStateChanged(onAuthStateChanged);
return () => unsubscribe();
}, []);
除了 googleOauth 注销之外,您还需要从 firebase 注销
const signOut = async () => {
try {
await GoogleSignin.signOut(); //GoogleOAuth logout
await auth().signOut(); //Firebase logout
console.log('Sign out');
} catch (error) {
console.error(error.message);
}};
谈论未处理的承诺拒绝,当您在使用“await”调用函数时不使用 try-catch 块时,就会发生这种情况
也许将来有人会遇到同样的问题,所以这就是造成这个问题的原因。这是 Recoil,显然这两个库不能很好地协同工作,所以我使用上下文重写了它并且工作得很好。
@kvba 我也一直在拉扯我剩下的头发,直到我终于弄清楚发生了什么。 Recoil 将冻结传递给原子的值,并且通过冻结传递给
onUserChanged
的用户对象,您可以有效地冻结 Firebase 身份验证对象的整个层次结构,因为 User 对象具有对其 Auth 实例和 AFAIK 的引用,调用 freeze( )将有效地冻结整个属性层次结构。一旦冻结,它就已设置并完成,这解释了为什么您必须重新启动应用程序才能使事情正常工作。
我的解决方案是存储 User 对象的克隆版本,而不是在原子中使用 Lodash
deepClone
。