I am trying to make an app in React Native using Expo Go. have successfully gotten google sign in working and it's all good. Unfortunately, the user's login does NOT persist between app relaunches. At first, I thought it was an async storage problem, but I can save items in storage just fine between relaunches.
What data would I need to save manually to be able to log the user back in whenever the app launches?
I would prefer to persist the data manually, as all the methods that are supposed to work, do not work for me. Methods I have tried:
setPersistence(getAuth(), browserLocalPersistence)
gives me an error, see this post for the exact error that I am getting.onAuthStateChanged
also does not work for me, in fact, that is the main way I know when to log in. The user object is just always null, and never changes from null until the user logs in again (which happens on every app launch).
useEffect(() => getAuth().onAuthStateChanged(value => {
if (value) {
console.log("User is signed in");
} else {
console.log("User is signed out");
// navigation.navigate("login")
}
}), [])
(This code will always print user is signed out on app relaunch.)
At this point, I think it would just be easier if I could just save the user's credentials myself and then log them in silently on app launch. I am having a hard time finding code to do this.
Ok, so I realized that to preserve login state, you actually have to do a special process if using expo. You need to initialize your own auth, passing in Async Storage, like so
import { initializeApp } from "firebase/app"
import { initializeAuth } from "firebase/auth"
import { getReactNativePersistence } from "firebase/auth/react-native"
import AsyncStorage from "@react-native-async-storage/async-storage"
const defaultApp = initializeApp(config);
initializeAuth(defaultApp, {
persistence: getReactNativePersistence(AsyncStorage)
});
You need to use SecureStore
to presist the data in the device. Something like LocalStorage
in web, SharedPreference
in Android and NSUserDefaults
in iOS.
Example:
// save your thing
async function save(key, value) {
await SecureStore.setItemAsync(key, value);
}
// get your thing
async function getValueFor(key) {
let result = await SecureStore.getItemAsync(key);
if (result) {
alert("🔐 Here's your value 🔐 \n" + result);
} else {
alert('No values stored under that key.');
}
}
Read more here: https://docs.expo.dev/versions/latest/sdk/securestore/
the idea is, save the JWT from Firebase in the SecureStore, so when the app start, check for this value, then use that JWT in secure store when calling to your API
@Bernard Allotey's answer is correct. Here is an example with the compat version of firebase 9
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
import 'firebase/compat/functions';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {initializeAuth} from 'firebase/auth';
import {getReactNativePersistence} from 'firebase/auth/react-native';
import firebaseConfig from './firebaseConfig';
const fireApp = firebase.initializeApp(firebaseConfig);
firebase.firestore();
firebase.functions();
// firebase.auth().setPersistence(firebase.auth.Auth.Persistence.LOCAL);
initializeAuth(fireApp, {
persistence: getReactNativePersistence(AsyncStorage),
});
export default firebase;