ReactNative Expo File Based Routing with Firebase Authentication
Aaron K Saunders
Posted on April 26, 2023
Expo Router brings the best routing concepts from the web to native iOS and Android apps. Every file in the app directory automatically becomes a route in your mobile navigation, making it easier than ever to build, maintain, and scale your project. https://expo.github.io/router/docs
Expo File Based Routing ( Part 1 )
The first part of working with Expo Router and File Based Navigation is covered in the video below
Firebase Authentication ( Part 2 )
The second part has the steps listed below with a video walking through the whole project in GitHub. Source code for both videos in included in the GitHub link at the end of the post.
We now export the auth object and use that throughout the application instead of calling getAuth in.
We want the app to remember logged in users so we need to add additional code. To check for an authenticated user we need to call onAuthStateChange when app launches and wait for a response before rendering the proper Navigation Stack.
In our store, we have added the user and the initialized properties to the application state. After the onAuthStateChange is triggered we update the store if there is a user, and we indicate that the application is now initialized. We can access the updated values through the store use those values in index.js
In index.js we wait for initialization to complete and then we take the appropriate action to redirect the user to the login route if there is no user or the tabs route if a user exists.
const{initialized,isLoggedIn}=AuthStore.useState();React.useEffect(()=>{if (!navigationState?.key||!initialized)return;constinAuthGroup=segments[0]==="(auth)";if (// If the user is not signed in and the initial segment is not anything// segment is not anything in the auth group.!isLoggedIn&&!inAuthGroup){// Redirect to the login page.router.replace("/login");}elseif (isLoggedIn){// go to tabs root.router.replace("/(tabs)/home");}},[segments,navigationState?.key,initialized]);
We wrap the firebase calls so we can update the store when appropriate. Below is the full listing of the calls for login, logout and create user account.
exportconstappSignIn=async (email,password)=>{try{constresp=awaitsignInWithEmailAndPassword(auth,email,password);AuthStore.update((store)=>{store.user=resp.user;store.isLoggedIn=resp.user?true:false;});return{user:auth.currentUser};}catch (e){return{error:e};}};exportconstappSignOut=async ()=>{try{awaitsignOut(auth);AuthStore.update((store)=>{store.user=null;store.isLoggedIn=false;});return{user:null};}catch (e){return{error:e};}};exportconstappSignUp=async (email,password,displayName)=>{try{// this will trigger onAuthStateChange to update the store..constresp=awaitcreateUserWithEmailAndPassword(auth,email,password);// add the displayNameawaitupdateProfile(resp.user,{displayName});AuthStore.update((store)=>{store.user=auth.currentUser;store.isLoggedIn=true;});return{user:auth.currentUser};}catch (e){return{error:e};}};