Как сохранить сессию авторизации Firebase в React Native с Expo? Пользователь сбрасывается после перезапуска приложения

Проблема с сохранением авторизации Firebase в React Native

Разрабатываю мобильное приложение на React Native с использованием Expo и Firebase для аутентификации. Столкнулся с проблемой - после успешного входа в систему пользователь не остается авторизованным при перезапуске приложения.

Что происходит

После перезагрузки или закрытия приложения пользователь снова попадает на экран входа, хотя до этого был успешно авторизован. В консоли показывается NULL вместо данных пользователя.

Что уже проверил

  • onAuthStateChanged() работает корректно при входе
  • После перезапуска возвращает null
  • AsyncStorage установлен и функционирует
  • Persistence настроен сразу после инициализации auth

Основной файл приложения

import { createStackNavigator } from '@react-navigation/stack';
import { NavigationContainer } from '@react-navigation/native';
import WelcomeScreen from './components/Welcome'
import Dashboard from './components/Dashboard'
import SignUp from './components/SignUp'
import SignIn from './components/SignIn'
import PolicyScreen from './components/Policy'
import useAuthState from './hooks/useAuthState';

const Navigator = createStackNavigator()

export default function MainApp() {
  const { currentUser, isLoading } = useAuthState();
  console.log("Текущий пользователь:", currentUser)

  if (isLoading) {
    return null;
  }

  return (
    <NavigationContainer>
      <Navigator.Navigator initialRouteName={currentUser ? 'Dashboard' : 'Welcome'}>
        {currentUser ? (
          <>
            <Navigator.Screen
              name='Dashboard'
              component={Dashboard}
              options={{ headerShown: false }}
            />
            <Navigator.Screen
              name='Policy'
              component={PolicyScreen}
              options={{ headerShown: false }}
            />
          </>
        ) : (
          <>
            <Navigator.Screen
              name='Welcome'
              component={WelcomeScreen}
              options={{ headerShown: false }}
            />
            <Navigator.Screen
              name='SignUp'
              component={SignUp}
              options={{ headerShown: false }}
            />
            <Navigator.Screen
              name='SignIn'
              component={SignIn}
              options={{ headerShown: false }}
            />
          </>
        )}
      </Navigator.Navigator>
    </NavigationContainer>
  );
}

Конфигурация Firebase

import { initializeApp } from 'firebase/app';
import { initializeAuth, getReactNativePersistence } from 'firebase/auth';
import AsyncStorage from "@react-native-async-storage/async-storage"

const config = {
  // конфигурация проекта
};

export const firebaseApp = initializeApp(config);

export const firebaseAuth = initializeAuth(firebaseApp, { 
  persistence: getReactNativePersistence(AsyncStorage) 
});

Хук для отслеживания авторизации

import { useEffect, useState } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import { firebaseAuth } from '../config/firebase';
 
export default function useAuthState() {
  const [authData, setAuthData] = useState({ currentUser: null, isLoading: true });

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(firebaseAuth, (authUser) => {
      console.log("Получен пользователь:", authUser)
      if (authUser) {
        setAuthData({ currentUser: authUser, isLoading: false })
      } else {
        setAuthData({ currentUser: null, isLoading: false })
      }
    });
    return unsubscribe
  }, []);
  return authData;
}

Возможно, есть какие-то нюансы с инициализацией Firebase или race condition? Буду благодарен за помощь в решении этой проблемы.

Добавь небольшую задержку в useAuthState перед тем как поставить isLoading в false. У меня была такая же фигня - Firebase не успевает подтянуть сессию из AsyncStorage до рендера компонента. Поставил setTimeout на 100-200мс после первого ответа от onAuthStateChanged и всё заработало. И ещё - проверь что firebaseAuth везде импортируется из одного файла, а не создаётся каждый раз заново.

У меня была такая же фигня пару месяцев назад! Скорее всего проблема в двойной инициализации auth. Замени initializeAuth на обычный getAuth из firebase/auth - если уже используешь expo, то этого хватит. У меня сработало - оказалось expo сам инициализирует auth, а когда делаешь это второй раз, получается конфликт. И еще - проверь через консоль разработчика, что AsyncStorage реально сохраняет данные. Иногда глючит с правами доступа.

А ты добавлял обработку ошибок в useAuthState? Firebase может молча падать при загрузке сессии. Проверь версии пакетов - у меня старая expo не работала с новой firebase. И еще - что с сетью? При плохом инете Firebase возвращает null вместо ожидания.