Firebase authstate 需要很长时间才能在慢速连接上对用户进行身份验证 - React Native

Firebase authstate takes long to authenticate user on slow connection - React Native

我正在创建一个连接到 firebase 的本机反应应用程序。 但是,当我以较慢的互联网速度启动我的应用程序时,需要一段时间才能加载,并且代码显示这是由于等待 authstate 侦听器在慢速连接上变慢造成的。在飞行模式下,它工作正常。

即使网速较慢,我怎样才能加快应用程序的加载速度?

import { getApps, initializeApp } from 'firebase/app';

// import 'firebase/compat/auth'
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged, signOut } from "firebase/auth";

// import 'firebase//firestore'
import { getFirestore, collection, addDoc, query, where, getDocs, deleteDoc, doc, setDoc, serverTimestamp } from "firebase/firestore"

import AsyncStorage from '@react-native-async-storage/async-storage';




// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {*****
};



// Initialize Firebase

if (!getApps().length) {
    console.log('initializing firebase');
    const app = initializeApp(firebaseConfig);
}

包:

{
  "name": "tut3",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "@gorhom/bottom-sheet": "^4",
    "@react-native-async-storage/async-storage": "^1.17.2",
    "@react-native-community/datetimepicker": "4.0.0",
    "@react-native-community/google-signin": "^5.0.0",
    "@react-native-firebase/app": "^14.7.0",
    "@react-native-firebase/auth": "^14.7.0",
    "@react-native-google-signin/google-signin": "^7.2.2",
    "@react-navigation/bottom-tabs": "^6.2.0",
    "@react-navigation/material-bottom-tabs": "^6.1.1",
    "@react-navigation/native": "^6.0.8",
    "@react-navigation/native-stack": "^6.5.2",
    "@react-navigation/stack": "^6.1.1",
    "expo": "~44.0.0",
    "expo-camera": "^12.1.2",
    "expo-fast-image": "^1.1.3",
    "expo-file-system": "~13.1.4",
    "expo-google-app-auth": "~8.3.0",
    "expo-image-picker": "^12.0.2",
    "expo-location": "~14.0.1",
    "expo-status-bar": "^1.2.0",
    "expo-updates": "~0.11.6",
    "firebase": "^9.6.10",
    "moment": "^2.29.1",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "react-native": "0.64.3",
    "react-native-action-button": "^2.8.5",
    "react-native-dropdown-picker": "^5.3.0",
    "react-native-gesture-handler": "~2.1.0",
    "react-native-gifted-chat": "^0.16.3",
    "react-native-image-crop-picker": "^0.37.3",
    "react-native-keyboard-aware-scroll-view": "^0.9.5",
    "react-native-maps": "0.29.4",
    "react-native-onboarding-swiper": "^1.2.0",
    "react-native-paper": "^4.12.0",
    "react-native-reanimated": "~2.3.1",
    "react-native-safe-area-context": "^4.2.4",
    "react-native-screens": "^3.13.1",
    "react-native-skeleton-placeholder": "^5.0.0",
    "react-native-stars": "^1.2.2",
    "react-native-vector-icons": "^9.1.0",
    "react-native-web": "0.17.1",
    "reanimated-bottom-sheet": "^1.0.0-alpha.22",
    "shorthash": "^0.0.2",
    "styled-components": "^5.3.5"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9"
  },
  "private": true
}

这是我的路线文件夹,用于确定在应用程序初始化完成之前在应用程序上显示的内容:

import React, { useContext, useState, useEffect } from 'react';
import { NavigationContainer } from '@react-navigation/native';

import { auth } from './AuthProvider';
// import 'firebase/compat/auth'
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged, signOut } from "firebase/auth";

// import 'firebase//firestore'
import { getFirestore, collection, addDoc, query, where, getDocs, deleteDoc, doc, setDoc } from "firebase/firestore"


import { AuthContext } from './AuthProvider';

import AuthStack from './AuthStack';
import AppStack from './AppStack';
import AsyncStorage from '@react-native-async-storage/async-storage';



const Routes = () => {
  const { user, setUser } = useContext(AuthContext);
  const [initializing, setInitializing] = useState(true);

  const onAuthStateChanges = (user) => {
    setUser(user);
    if (initializing) setInitializing(false);
    console.log(user)
  };
  
  useEffect(() => {
    
    const subscriber = onAuthStateChanged(auth, onAuthStateChanges);
    return subscriber; // unsubscribe on unmount
    
  }, []);

  if (initializing) return null;


  return (
    <NavigationContainer>
      {user ? <AppStack /> : <AuthStack />}
    </NavigationContainer>
  )
  
};

export default Routes;

谢谢!

编辑: 在建议的答案之后,这就是我已经实现的似乎对我有用的东西。想法是,如果用户之前登录并退出应用程序而没有注销,则加载应用程序堆栈。

const Routes = () => {
  const { user, setUser } = useContext(AuthContext);
  const [initializing, setInitializing] = useState(true);
  const [previousUser, setPreviousUser] = useState(null);

  const onAuthStateChanges = (user) => {
    setUser(user);
    AsyncStorage.setItem('user', JSON.stringify(user));
    if (initializing) setInitializing(false);
    console.log(user)
  };

  useEffect(() => {
    AsyncStorage.getItem('user').then((value) => {
      if (value) {
        setPreviousUser(true)
        setUser(JSON.parse(value))
      }
      else {
        setPreviousUser(false)
      }

    })


    const subscriber = onAuthStateChanged(auth, onAuthStateChanges);
    return subscriber; // unsubscribe on unmount

  }, []);

  if (initializing && user) return (
    <NavigationContainer>
      <AppStack />
    </NavigationContainer>
  ) 

  if (initializing && !user) return (
    <NavigationContainer>
      <AuthStack />
    </NavigationContainer>
  ) 

  return (


    <NavigationContainer>
      {!initializing && user ? <AppStack /> : <AuthStack />}
    </NavigationContainer>

  )



};

initializeApp 的调用是同步的,不需要调用服务器,因此 运行 应该非常快,而且速度与您的互联网连接无关。

但是 onAuthStateChanged 等待身份验证状态恢复, 需要调用服务器来检查用户的凭据是否仍然有效(例如,他们的帐户没有被禁用)。如果互联网连接速度较慢,这可能需要一些时间。

由于大多数此类调用都会成功,所以一个常见的技巧是假设它们会成功,然后如果事实证明该假设是错误的,则当然会更正。要实现这一点,您需要在用户成功登录后在本地存储中存储一个令牌值,然后使用 that 值来确定您的初始导航,而不是等待 onAuthStateChanged.

Firebaser Michael Bleigh 在 Architecting Mobile Web Apps 上的 Google I/O 视频中谈到了这一点。