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
相关产品推荐
相关产品推荐

