skip to Main Content

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


  1. 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:

    useEffect(() => {
      if (user) {
        setLoading(false)
      }
    }, [user])
    
    Login or Signup to reply.
  2. I have the same issue, still looking for a solution… I tried few things like upgrading Firebase, without any luck.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search