Using ReactFire with Ionic Framework & Capacitor

Aaron K Saunders - Jul 21 '20 - - Dev Community

🔆Click Here for Ionic Framework ReactJS and VueJS Tips/Tutorials?🔆

Sample project motivated by video by David East on Reactfire

You should know that Reactfire is not considered "Production"

Overview

Required

you must create a file called src/env.js and add the following code

export const FIREBASE_CONFIG = {
// YOUR FIREBASE CONFIGURATION
};

// NAME OF COLLECTION IN FIREBASE TO LIST
export const FIREBASE_COLLECTION_NAME = "users"

// THIS IS REQUIRED FOR ANDROID
// SEE - https://github.com/FirebaseExtended/reactfire/issues/228
global.globalThis = window;
Enter fullscreen mode Exit fullscreen mode

Code Snippets

Checking Authentication Status At Startup

Here is the app it is much cleaner to check auth status and redirect the user appropriately, all of the listening for authChangeStatus and such is all gone...

If the authCheck fails, then we use the Login component.

const App: React.FunctionComponent = () => {
  return (
    <FirebaseAppProvider firebaseConfig={FIREBASE_CONFIG}>
      <IonApp>
        <IonReactRouter>
          <IonRouterOutlet>
            <Suspense fallback={<IonLoading isOpen={true} />}>
              <AuthCheck fallback={<Login />}>
                <Home />
              </AuthCheck>
            </Suspense>
          </IonRouterOutlet>
        </IonReactRouter>
      </IonApp>
    </FirebaseAppProvider>
  );
};
Enter fullscreen mode Exit fullscreen mode

Logging The User In

This is a 'hack' that is currently needed to address issues with clearing information between authenticated sessions. As stated above, this is not production ready code.

This code was pulled from the issue in github where a work around was presented.

I found that this work around did not work on the android browser because the globalThis object was undefined. To resolve this issue, I set globalThis to window in the env.js file.

export const FIREBASE_CONFIG = {
// YOUR FIREBASE CONFIGURATION
};

// NAME OF COLLECTION IN FIREBASE TO LIST
export const FIREBASE_COLLECTION_NAME = "users"

// THIS IS REQUIRED FOR ANDROID
// SEE - https://github.com/FirebaseExtended/reactfire/issues/228
global.globalThis = window;
Enter fullscreen mode Exit fullscreen mode
  // SEE - https://github.com/FirebaseExtended/reactfire/issues/228
  useEffect(() => {
    let map = (globalThis as any)["_reactFirePreloadedObservables"];
    map &&
      Array.from(map.keys()).forEach(
        (key: any) => key.includes("firestore") && map.delete(key)
      );
  }, []);
Enter fullscreen mode Exit fullscreen mode

Here we use the useAuth hook to get the auth object to call the signInWithEmailAndPassword method

  const auth = useAuth();
  /**
   * get data from form and sign the user in
   */
  const signIn = async (data: any) => {
    try {
      let r = await auth.signInWithEmailAndPassword(data.email, data.password);
      console.log(r);
    } catch (e) {
      setShowErrorAlert(e.message);
    }
  };
Enter fullscreen mode Exit fullscreen mode

Rendering A Collection from the Database

  • use the useAuth hook to get auth object for logging the user out.
  • use the useFirebaseApp hook to get firebaseApp collection
  • use the useFirestoreCollectionData to get the data collection to render.
const Home: React.FunctionComponent = () => {
  const auth = useAuth();
  const thingsRef = useFirebaseApp()
    .firestore()
    .collection(FIREBASE_COLLECTION_NAME);
  const data = useFirestoreCollectionData(thingsRef, { idField: "id" });

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar color="light">
          <IonButtons slot="end">
            <IonButton onClick={() => auth.signOut()}>Logout</IonButton>
          </IonButtons>
          <IonTitle>Home</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent className="ion-padding">
        <AuthCheck fallback={<IonLoading isOpen={true} />}>
          <IonList>
            {data.map((e: any) => {
              return (
                <IonItem key={e.id}>
                  <IonLabel className="ion-text-wrap">
                    {JSON.stringify(e)}
                  </IonLabel>
                </IonItem>
              );
            })}
          </IonList>
        </AuthCheck>
      </IonContent>
    </IonPage>
  );
};
Enter fullscreen mode Exit fullscreen mode

Whats Next

  • Add Items Using Ionic Modal
  • Delete Items using IonSlidingItem
  • Create Account

Source Code

ko-fi

ionic-react-hook-form-react-fire

Last Updated 8/16/2020

Releases and tags coincide with specific blog posts in the series See Blog Series

Sample project motivated by video by David East on Reactfire

Saves The Following Data Structure

I am starting to integrated typescript into my examples since I am seeing questions about types popping up in the forums. The IModalData is the structure of the data that is written to…

See Other Work On My YouTube Channel

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .