为什么 onAuthStateChanged 监听器在移除后仍然在监听
Why is the onAuthStateChanged Listener still listening even after removing
我有两个屏幕.. 第一个是初始屏幕,我在 firebase.auth().onAuthStateChanged 侦听器的帮助下检查用户是否已经存在。如果用户为空,它将移动到登录屏幕,其中另一个 firebase.auth().onAuthStateChanged 监听器用于在 phone 验证后获取用户,并将用户移动到任一 UserDetails 屏幕以获取更多用户信息如果用户之前没有注册或移动到主屏幕..在启动屏幕上也进行相同的检查以确保只有在用户输入详细信息后才会显示主屏幕..问题是在登录屏幕上, 在 phone 验证完成后, firebase.auth() 检测到用户登录, 启动画面的侦听器也会被执行, 有时会导致致命崩溃..
那么,我应该如何正确删除登录屏幕上的侦听器??我的方法不对。
动画在启动画面上显示的时间延迟
这是初始屏幕上的代码:
try{
if(!firebase.apps.length){
firebase.initializeApp(firebaseConfig);
}
}catch(err){
console.log(err);
}
const cacheResourcesAsync = async () => {
//Images to be loaded
];
const cacheImages = images.map(image => {
return Asset.fromModule(image).downloadAsync();
});
return Promise.all(cacheImages);
}
export const SplashLoadingScreen = () => {
const [isReady, setIsReady] = useState(false);
const [isFire, setIsFire] = useState(false);
const [isFont, setIsFont] = useState(false);
const [isImages, setIsImages] = useState(false);
const navigation = useNavigation();
var unsubscribe;
//Loading Fonts
const [michromaLoaded] = useMichroma({ Michroma_400Regular });
const [latoLoaded] = useLato({ Lato_700Bold });
//Checking if the fonts are ready
useEffect(() => {
if(michromaLoaded && latoLoaded){
setIsFont(true);
}
}, [michromaLoaded, latoLoaded]);
//Checking if the Images are loaded or not
useEffect(() => {
cacheResourcesAsync();
setIsImages(true);
return () => unsubscribe = undefined;
}, []);
//Checking if Firebase is fired up
useEffect(() => {
if(firebase.apps.length !== 0){
setIsFire(true);
}
}, [firebase.apps.length]);
//Last Check before moving to other screen
useEffect(() => {
if(isFont && isImages && isFire){
setTimeout(() => {
setIsReady(true); // Animation Purpose
}, 5000);
}
}, [isFont, isImages, isFire]);
//Moving to other screens
useEffect(() => {
if(isReady){
unsubscribe = firebase.auth().onAuthStateChanged((user) => {
if (user) {
firebase.firestore().collection("User Details").doc(firebase.auth().currentUser.uid).get().then((snap) => {
if(snap.exists){
navigation.navigate('Tab');
console.log("Splash"); //Used to check if the listener is still working on login screen
}else {
navigation.navigate('User');
console.log("Splash");
}
});
return;
}
navigation.navigate("SignUp");
});
}
}, [isReady]);
SplashScreen.hideAsync();
How am I supposed to remove the listener on Login Screen properly
onAuthStateChanged()
函数实际上是returns一个可以调用取消订阅的函数。
所以,既然你这样做了
unsubscribe = firebase.auth().onAuthStateChanged((user) => {...});
您只需调用 unsubscribe()
即可“移除侦听器”。请参阅括号,因为它是一个函数。
所以,如果我正确理解你的情况,你应该在 navigation.navigate(...)
调用之前调用它。
我有两个屏幕.. 第一个是初始屏幕,我在 firebase.auth().onAuthStateChanged 侦听器的帮助下检查用户是否已经存在。如果用户为空,它将移动到登录屏幕,其中另一个 firebase.auth().onAuthStateChanged 监听器用于在 phone 验证后获取用户,并将用户移动到任一 UserDetails 屏幕以获取更多用户信息如果用户之前没有注册或移动到主屏幕..在启动屏幕上也进行相同的检查以确保只有在用户输入详细信息后才会显示主屏幕..问题是在登录屏幕上, 在 phone 验证完成后, firebase.auth() 检测到用户登录, 启动画面的侦听器也会被执行, 有时会导致致命崩溃..
那么,我应该如何正确删除登录屏幕上的侦听器??我的方法不对。
动画在启动画面上显示的时间延迟
这是初始屏幕上的代码:
try{
if(!firebase.apps.length){
firebase.initializeApp(firebaseConfig);
}
}catch(err){
console.log(err);
}
const cacheResourcesAsync = async () => {
//Images to be loaded
];
const cacheImages = images.map(image => {
return Asset.fromModule(image).downloadAsync();
});
return Promise.all(cacheImages);
}
export const SplashLoadingScreen = () => {
const [isReady, setIsReady] = useState(false);
const [isFire, setIsFire] = useState(false);
const [isFont, setIsFont] = useState(false);
const [isImages, setIsImages] = useState(false);
const navigation = useNavigation();
var unsubscribe;
//Loading Fonts
const [michromaLoaded] = useMichroma({ Michroma_400Regular });
const [latoLoaded] = useLato({ Lato_700Bold });
//Checking if the fonts are ready
useEffect(() => {
if(michromaLoaded && latoLoaded){
setIsFont(true);
}
}, [michromaLoaded, latoLoaded]);
//Checking if the Images are loaded or not
useEffect(() => {
cacheResourcesAsync();
setIsImages(true);
return () => unsubscribe = undefined;
}, []);
//Checking if Firebase is fired up
useEffect(() => {
if(firebase.apps.length !== 0){
setIsFire(true);
}
}, [firebase.apps.length]);
//Last Check before moving to other screen
useEffect(() => {
if(isFont && isImages && isFire){
setTimeout(() => {
setIsReady(true); // Animation Purpose
}, 5000);
}
}, [isFont, isImages, isFire]);
//Moving to other screens
useEffect(() => {
if(isReady){
unsubscribe = firebase.auth().onAuthStateChanged((user) => {
if (user) {
firebase.firestore().collection("User Details").doc(firebase.auth().currentUser.uid).get().then((snap) => {
if(snap.exists){
navigation.navigate('Tab');
console.log("Splash"); //Used to check if the listener is still working on login screen
}else {
navigation.navigate('User');
console.log("Splash");
}
});
return;
}
navigation.navigate("SignUp");
});
}
}, [isReady]);
SplashScreen.hideAsync();
How am I supposed to remove the listener on Login Screen properly
onAuthStateChanged()
函数实际上是returns一个可以调用取消订阅的函数。
所以,既然你这样做了
unsubscribe = firebase.auth().onAuthStateChanged((user) => {...});
您只需调用 unsubscribe()
即可“移除侦听器”。请参阅括号,因为它是一个函数。
所以,如果我正确理解你的情况,你应该在 navigation.navigate(...)
调用之前调用它。