You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native + Expo下Firebase用户登录状态无法持久化问题

Firebase用户登录状态在Expo重载后丢失的问题及解决办法

问题描述

我耗时数日排查Firebase用户登录状态持久化问题:使用Expo重载应用时,用户每次都会被登出,onAuthStateChanged会触发但返回的user为null。不确定是代码存在问题,还是该问题与Expo相关。

相关代码示例

SignIn组件

import React, { useState } from 'react';
import { Image, TouchableOpacity, View } from 'react-native';
import { Button, Text, TextInput } from 'react-native-paper';
import { theme } from '../../src/theme';
import { authStyle } from '../../styles/authStyle';
import { mainStyle } from '../../styles/mainStyle';
import Alert from '../Alert';
import { auth } from '../../src/Firebase';
import { signInWithEmailAndPassword } from "firebase/auth";

const SignInScreen = ({ navigation }) => {
  const [email, setEmail] = useState('');
  const [securePassword, setSecurePassword] = useState(true);
  const [password, setPassword] = useState('');
  const [isLoading, setIsLoading] = useState(false);
  const [alert, setAlert] = useState({ visible: false, message: '', type: 'error' });

  const handleSignIn = async () => {
    setIsLoading(true);
    try {
      await signInWithEmailAndPassword(auth, email, password);
      setAlert({ visible: true, message: 'Connexion réussie!', type: 'success' });
    } catch (e) {
      console.log(e)
      setAlert({ visible: true, message: e.message, type: 'error' });
    }
    setIsLoading(false);
  };

  const onDismissAlert = () => {
    setAlert({ ...alert, visible: false });
  };

  return (
    <View style={mainStyle.container}>
      <View style={[mainStyle.pageContainer, {alignItems: 'center', backgroundColor: '#ffffff'}]}>
        <View style={authStyle.header}>
          <Image
            style={{width: 200, height: 200}}
            source={require('../../assets/app_icon.png')}
          />
          <Text style={authStyle.headerHeadline}>Connexion</Text>
        </View>
        <TextInput
            label="Email"
            value={email}
            theme={theme} 
            mode='outlined'
            style={authStyle.input}
            outlineColor={theme.outlineColor}
            outlineStyle ={theme.outlineStyle}
            onChangeText={(email) => setEmail(email.trim())}
            autoCapitalize='none'
            left={<TextInput.Icon icon="account" />}
        />
        <TextInput
            label="Mot de passe"
            value={password}
            theme={theme}
            mode="outlined"
            secureTextEntry={securePassword}
            style={authStyle.input}
            outlineColor={theme.outlineColor}
            outlineStyle ={theme.outlineStyle}
            onChangeText={setPassword}
            left={<TextInput.Icon icon="lock" />}
            right={<TextInput.Icon iconColor={theme.colors.primary} onPress={() => setSecurePassword(!securePassword)} icon="eye" />} 
        />
        <View style={authStyle.button}>
          <Button
              mode="contained"
              onPress={handleSignIn}
              style={theme.submitButton.style}
              loading={isLoading}
              disabled={isLoading}
              labelStyle={theme.submitButton.labelStyle}
          >
              Se connecter
          </Button>
        </View>
        <Text style={{color: theme.colors.primary, fontSize: 16, fontWeight: theme.bold, marginTop: 10}}>Mot de passe oublié?</Text>
        <View style={{justifyContent: 'flex-end', flexGrow: 1, flexDirection: 'row', alignItems: 'flex-end'}}>
          <Text style={{fontWeight: theme.bold}}>Pas de compte? </Text>
          <TouchableOpacity onPress={() => navigation.navigate('SignUp')}>
            <Text style={{color: theme.colors.primary, fontWeight: theme.bold}}>Inscrivez vous</Text>
          </TouchableOpacity>
        </View>
      </View>
      <Alert visible={alert.visible} message={alert.message} type={alert.type} onDismiss={onDismissAlert} /> 
    </View>
  );
};

export default SignInScreen;

App.js

import React, { useEffect, useState } from 'react';
import { SafeAreaView, StyleSheet } from 'react-native';
import { Provider as PaperProvider } from 'react-native-paper';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import AppScreen from './Components/AppScreen';
import AuthScreen from './Components/AuthScreen';
import { theme } from './src/theme';
import { auth } from './src/Firebase';
import { onAuthStateChanged } from "firebase/auth";


export default function App() {
  
  const [user, setUser] = useState(null);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      if (user) { 
        setUser(user);
      } else {
        setUser(null);
      }
    });

    return unsubscribe;
  }, []);

  return (
    <SafeAreaProvider>
      <PaperProvider theme={theme}>
        <SafeAreaView style={styles.container}>
          {user ? (
            <AppScreen /> 
          ) : (
            <AuthScreen />
          )}
        </SafeAreaView> 
      </PaperProvider>
    </SafeAreaProvider>
  );
}

const styles = StyleSheet.create({
  container:{
    flex:1,
    backgroundColor: "#fff"
  }
});

Firebase.js

import { initializeApp } from "firebase/app";
import { getAuth, browserSessionPersistence, setPersistence  } from "firebase/auth";
import { getFirestore } from 'firebase/firestore/lite';
import { firebaseConfig } from "./firebaseconfig";
  
const firebase = initializeApp(firebaseConfig);

export const db = getFirestore(firebase);
export const auth = getAuth(firebase);

package.json

{
  "name": "musculation",
  "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"
  },
  "dependencies": {
    "@react-native-firebase/app": "^17.5.0",
    "@react-native-firebase/auth": "^17.5.0",
    "@react-navigation/native": "^6.1.6",
    "@react-navigation/native-stack": "^6.9.12",
    "expo": "~48.0.15",
    "expo-status-bar": "~1.4.4",
    "firebase": "^9.21.0",
    "react": "18.2.0",
    "react-native": "0.71.7",
    "react-native-gesture-handler": "~2.9.0",
    "react-native-paper": "^5.7.2"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0"
  },
  "private": true
}

已尝试的操作

  • 重载应用
  • 关闭并重新启动Expo应用

问题依旧存在。

解决方案

由于希望继续使用便捷的Expo GO,我移除了rnfirebase依赖(@react-native-firebase/app和@react-native-firebase/auth),保留原有代码后重新安装firebase,按相关方案操作后,问题已解决。


内容的提问来源于stack exchange,提问作者Keldryn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 23:34:55