【问题标题】:Why is the onAuthStateChanged Listener still listening even after removing为什么即使删除后 onAuthStateChanged 侦听器仍在侦听
【发布时间】:2021-12-31 06:38:08
【问题描述】:

我有两个屏幕.. 首先是启动屏幕,我在 firebase.auth().onAuthStateChanged Listener 的帮助下检查用户是否已经存在。如果用户为空,则移动到登录屏幕,其中另一个 firebase.auth().onAuthStateChanged 侦听器用于在电话验证后获取用户,如果用户未注册,则将用户移动到任一 UserDetails 屏幕以获取更多用户信息之前或移动到主屏幕..在启动屏幕上也进行了相同的检查,以确保只有在用户输入他的详细信息后才会显示主屏幕..问题是在登录屏幕上,电话验证后完成,并且 firebase.auth() 检测到用户登录,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();

【问题讨论】:

    标签: javascript firebase react-native firebase-authentication expo


    【解决方案1】:

    我应该如何正确删除登录屏幕上的监听器

    onAuthStateChanged() 函数实际上返回一个函数,您可以调用它来取消订阅。

    所以,既然你这样做了

    unsubscribe = firebase.auth().onAuthStateChanged((user) => {...});
    

    您只需致电unsubscribe() 即可“移除监听器”。看括号,因为它是一个函数。


    所以,如果我正确理解你的情况,你应该在navigation.navigate(...) 调用之前调用它。

    【讨论】: