I have two screens .. First is the Splash Screen where I check if a user already exists with help of firebase.auth().onAuthStateChanged Listener. If the user is null, it moves to the login screen where another firebase.auth().onAuthStateChanged Listener is used to get the user after phone verification and move the user to either UserDetails Screen to get more user info if the user is not registered before or move to the main screen .. The same check is done on splash screen as well to ensure that user is shown the main screen only after he has entered his details.. The problem is that on Login Screen , after the phone verification is completed, and firebase.auth() detects a user sign in, the listener of Splash Screen also gets executed causing a fatal crash sometimes..
So, how am I supposed to remove the listener on Login Screen properly?? My way isn't working properly.
The time delay is for the animation to be displayed on splash screen
Here's the code on Splash Screen :
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();
CodePudding user response:
How am I supposed to remove the listener on Login Screen properly
The onAuthStateChanged()
function actually returns a function that you can call to unsubscribe.
So, since you do
unsubscribe = firebase.auth().onAuthStateChanged((user) => {...});
you just have to call unsubscribe()
to "remove the listener". See the brackets since it is a function.
So, if I correctly understand your case, you should call it before the navigation.navigate(...)
calls.