I’m using ReactNativeAsyncStorage
to persist a Firebase User. However, my user is not being persisted upon reload of the application. The useAuth hook does work when the app is loaded. What am I doing wrong here?
FIREBASE CONFIG
import { initializeApp } from "firebase/app";
import { initializeAuth, getReactNativePersistence } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import ReactNativeAsyncStorage from "@react-native-async-storage/async-storage";
const firebaseConfig = {
...
};
export const FIREBASE_APP = initializeApp(firebaseConfig);
export const FIREBASE_AUTH = initializeAuth(FIREBASE_APP, {
persistence: getReactNativePersistence(ReactNativeAsyncStorage),
});
export const FIREBASE_FIRESTORE = getFirestore(FIREBASE_APP);
AUTH HOOK
import { createContext, useContext, useEffect, useState } from "react";
import { FIREBASE_AUTH } from "../config/firebase";
import { onAuthStateChanged, signInAnonymously } from "firebase/auth";
const AuthContext = createContext();
export function Provider({ children }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const unsubscribe = onAuthStateChanged(FIREBASE_AUTH, (user) => {
if (user) {
setUser(user);
setLoading(false);
} else {
setUser(null);
setLoading(false);
}
});
return () => {
unsubscribe();
};
}, [user]);
const authSignInAnonymously = async () => {
try {
const userCredential = await signInAnonymously(FIREBASE_AUTH);
setUser(userCredential.user);
} catch (error) {
setUser(null);
console.log(error);
}
};
return (
<AuthContext.Provider
value={{
user,
loading,
authSignInAnonymously,
}}>
{children}
</AuthContext.Provider>
);
}
export const useAuth = () => {
const authContext = useContext(AuthContext);
if (!authContext) {
throw new Error("useAuth must be used within an AuthContextProvider");
}
return authContext;
};
APP.JS
import { NavigationContainer } from "@react-navigation/native";
import { Provider, useAuth } from "./app/hooks/useAuth";
import { PublicLayout } from "./app/layout/PublicLayout";
import { PrivateLayout } from "./app/layout/PrivateLayout";
export default function App() {
return (
<Provider>
<Navigator />
</Provider>
);
}
const Navigator = () => {
const { loading, user } = useAuth();
return (
<NavigationContainer>
{user && !loading ? <PrivateLayout /> : <PublicLayout />}
</NavigationContainer>
);
};
2
Answers
In your Provider useEffect, the setters are async and you probably set the loading boolean to false before the user has been set.
You should add another useEffect:
I have the same issue, still looking for a solution… I tried few things like upgrading Firebase, without any luck.