Search code examples
javascriptfirebasereact-nativefirebase-authenticationexpo

Firebase delay in fetching user


I have an app and want to make it so, when the app boots up, it checks if the user has set a state that indicates they want to stay signed in. If they did it brings them to home screen, if they didnt it brings them to the normal launch page. I have this:

const app = initializeApp(firebaseConfig);
const auth = initializeAuth(app, {
  persistence: getReactNativePersistence(AsyncStorage),
});

  useEffect(() => {
    const checkAuthStatus = async () => {
      try {
        const staySignedIn = await AsyncStorage.getItem("staySignedIn");
        const authInstance = getAuth();
        const user = authInstance.currentUser;

        const lastLoginTime = await AsyncStorage.getItem("lastLoginTime");

        if (lastLoginTime) {
          const currentTime = new Date();
          const lastLoginDate = new Date(lastLoginTime);

          const diffInTime = currentTime - lastLoginDate;
          const diffInDays = diffInTime / (1000 * 3600 * 24);

          if (diffInDays > 90) {
            await signOut(authInstance);
            await AsyncStorage.removeItem("lastLoginTime");
            await AsyncStorage.removeItem("staySignedIn");
            setLoading(false);
            return;
          }
        }

        if (staySignedIn === "true" && user) {
          router.push("/(tabs)/shared/Home");
        } else {
          setLoading(false);
        }
      } catch (error) {
        console.error("Error checking authentication status:", error);
        setLoading(false);
      }
    };

    checkAuthStatus();
  }, []);

`

It seems as though it takes around .03 seconds for firebase to fetch the user... longer than it takes for my component to mount. This means that even if there is a user, it returns null for them. I thought about listening for a state change in auth, but the problem is that if the user is actually null, the state doesn't change, and then the next time the state changes (say they hit the sign up button where it is supposed to bring them to an otp screen) it will behave as if they had been a logged in user and bring them to the home screen. Is there anything I can do aside from adding a delay?

I was attempting to have a user that chooses to stay logged in be logged in, without changing any other functionality of my application.


Solution

  • I thought about listening for a state change in auth

    That's the right thing to do.

    the problem is that if the user is actually null

    That's expected - currentUser is null until Firebase has been able to validate the user's previously persisted token. That's why you should use a listener instead.

    See:

    Is there anything I can do aside from adding a delay?

    The listener is the right way to go, and this is the case for all application platforms. Since you can't know for sure, immediately when an app launches, whether or not a user is actually signed in, you should initially show some sort of spinner or other implicit delay component that lasts until the auth state listener gives you a user object or null. At that point, you know you can switch from the spinner to navigating to where the signed-in user is supposed to go, or to ask them to sign in.