How to do a correct login setup with Firebase?

Hi, I’m having some difficulties with setting up a login flow with Firebase Auth.

I’m using the following setup (generated with Framework7 CLI):
framework: core
bundler: web pack
type: pwa and web

app.js
routes.js (using components)

app.f7.html
login.f7.html
home.f7.html

  1. Where do I need to initialise the firebase?
  2. How to setup the routes in order to get the currentUser from Firebase and to redirect either to ‘Login’ or ‘Home’?
  3. I know there’s also this ‘firebase.auth().onAuthStateChanged((user))’ event, but I don’t know If I need it for this login flow as well.

Or when the login screen is a popup inside app.f7.html, so no separate login.f7.html.

@Timo has a good and simple video showing how to make f7+firebase login;

User Authentication for Framework7 using Firebase | Beginner Example Tutorial How-To - YouTube

@pvtallulah Thank you for your reply! Yes, I have seen that video, but I need some more assistance on how to force the user to login at app start. When does Firebase needs to be initialized in this case and when do I need to redirect the user to the login if its not logged in yet?

all depends what is your need. Give a reat to Async Routes. Maybe its what you are loonking for.

routes = [
  {
    path: '/foo/',
    async(routeTo, routeFrom, resolve, reject) {
      // Here check with firebase if user is logedin
      if (userIsLoggedIn) {
        resolve({ url: 'home.html' })
      } else {
        resolve({ url: 'login.html' })
      }
    }
  }
]

Routes | Framework7 Documentation

I now have the following setup, but the user is always null. Any ideas?

routes.js:

import Login from '../pages/login.f7.html';

import Home from '../pages/home.f7.html';

// Import Firebase
import firebase from 'firebase/app';
import 'firebase/auth';

const firebaseConfig = {
// hidden
};

const firebaseApp = firebase.initializeApp(firebaseConfig);

var user = firebase.auth().currentUser;

var routes = [
  {
    path: '/',
    async(routeTo, routeFrom, resolve, reject) {
      if (user) {
        resolve({
          component: Home,
        });
      } else {
        resolve({
          loginScreen: {
            component: Login,
          } ,
        });
      }
    },
  },
];

export default routes;

no idea, did yo logged in?
will try to make a small tutorial with f7 and different options of logins. Since this is a common question.
But right now i dont have the time.

@pvtallulah Thanks that would be really nice.

By the way, I’m one step closer towards my goal. The only thing I’m currently not satisfied with, is that when I open the app, the Home Screen is visible until the onAuthStateChanged event is fired. And want to avoid that. Please check my setup here below:

app.js

  • Firebase Auth is initialised here
import $$ from 'dom7';
import Framework7 from 'framework7/framework7.esm.bundle.js';

// Import F7 Styles
import 'framework7/css/framework7.bundle.css';

// Import Icons and App Custom Styles
import '../css/icons.css';
import '../css/app.scss';

// Import Firebase
import firebase from 'firebase/app';
import 'firebase/auth';

const firebaseConfig = {
  // My config variables
};

const firebaseApp = firebase.initializeApp(firebaseConfig);

// Import Routes
import routes from './routes.js';

// Import main app component
import App from '../app.f7.html';

var app = new Framework7({
  // The usual stuff
});

routes.js

  • The main route navigates to Home
  • Login route opens the LoginScreen modal inside Login
import Login from '../pages/login.f7.html';
import Home from '../pages/home.f7.html';

var routes = [
  {
    path: '/',
    component: Home,
  },
  {
    path: '/login/',
    loginScreen: {
      component: Login,
    }
  },
];

export default routes;

app.f7.html

  • App template (F7 CLI): tabs => Views as Tabs
  • view-home is view-main
  • Here is the login method defined as well
  • And also the Firebase event onAuthStateChanged
    • If logged in: navigate to /
    • Else: navigate to login
<template>
  <div id="app">

    <!-- Views/Tabs container -->
    <div class="views tabs safe-areas">
      <!-- Tabbar for switching views-tabs -->
      <div class="toolbar toolbar-bottom tabbar">
        <div class="toolbar-inner">
          <a href="#view-home" class="tab-link toggle-fill tab-link-active">
            <i class="icon f7-icons filled-icon">today_fill</i>
            <i class="icon f7-icons outlined-icon">today</i>
          </a>
        </div>
      </div>

      <!-- Your main view/tab, should have "view-main" class. It also has "tab-active" class -->
      <div id="view-home" class="view view-main tab tab-active"></div>

    </div>
  </div>
</template>

<script>
import firebase from 'firebase/app';
import 'firebase/auth';

export default {
  data() {
    return {
      user: null,
      username: '',
      password: '',
    };
  },
  methods: {
    updateUsername(e) {
      this.username = e.target.value;
      this.$update();
    },
    updatePassword(e) {
      this.password = e.target.value;
      this.$update();
    },
    onLogin() {
      this.$f7.dialog.preloader();
      firebase.auth().signInWithEmailAndPassword(this.username, this.password)
        .then((user) => {
          // Dummy action
        })
        .catch((error) => {
          console.log(error);
          this.$f7.dialog.close();

          // Using a switch for translating the error codes
          switch (error.code) {
            case 'auth/invalid-email':
              this.$f7.dialog.alert('Controleer je e-mailadres en probeer het opnieuw.', 'Ongeldig e-mailadres');
              break;
            case 'auth/wrong-password':
              this.$f7.dialog.alert('Probeer het opnieuw of kies \'Wachtwoord vergeten\'.', 'Ongeldig wachtwoord');
              break;
            default:
              this.$f7.dialog.alert(error.message, 'Onbekende fout');
          }
        });
    },
    onPwReset() {
      // TO DO: Firebase password reset
    },
    onLogout() {
      // TO DO: Firebase logout
    },
  },
  mounted() {
    this.$f7ready(() => {
      const $ = this.$$;
      const app = this.$f7;

      // Checking Firebase Auth state
      firebase.auth().onAuthStateChanged((user) => {
        console.log('User auth status has changed!', user)
        this.user = firebase.auth().currentUser;
        console.log(this.user);
        if (user){
          app.views.main.router.navigate('/', {transition: 'f7-fade'})
          this.$f7.dialog.close();
        } else {
          app.views.main.router.navigate('/login/')
        }
      });

      var mainView = app.views.create('#view-home', {
        name: 'home',
        url: '/',
      });
    });
  }
}
</script>

login.f7.html

  • This template only has the LoginScreen modal
  • All methods are passed to the $root methods
<template>
<!-- Login Screen -->
<div class="login-screen" id="app-login-screen">
  <div class="view">
    <div class="page">
      <div class="page-content login-screen-content">
       // LoginScreen content
      </div>
    </div>
  </div>
</div>
</template>

<script>
export default {
  methods: {
    updateUsername(e) {
      this.$root.updateUsername(e);
    },
    updatePassword(e) {
      this.$root.updatePassword(e);
    },
    onLogin() {
      this.$root.onLogin();
    },
    toggleLoginForm() {
      this.$('#passwordResetForm').toggleClass('display-none');
      this.$('#loginForm').toggleClass('display-none');
    },
    onPwReset() {
      this.$root.onPwReset();
    }
  }
}
</script>

Below is my Complete App.jsx Where I use firebase Login, User Profile Creation and Logout.

import React from 'react';
import { Device } from 'framework7/framework7-lite.esm.bundle.js';
import {
  App,
  Panel,
  Views,
  View,
  Popup,
  Page,
  Navbar,
  Toolbar,
  NavRight,
  Link,
  Block,
  BlockTitle,
  LoginScreen,
  LoginScreenTitle,
  List,
  ListItem,
  ListInput,
  ListButton,
  BlockFooter
} from 'framework7-react';

import cordovaApp from '../js/cordova-app';

import routes from '../js/routes';

import StyledFirebaseAuth from 'react-firebaseui/StyledFirebaseAuth';

import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';

// Configure Firebase.
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: "XXXXXXXXXXXXX-XXXXXXXXXXXXX",
  authDomain: "my-sample-react-app.firebaseapp.com",
  projectId: "my-sample-react-app",
  storageBucket: "my-sample-react-app.appspot.com",
  messagingSenderId: "XXXXXXXXXXX",
  appId: "XXXXXXXXXXXXXX",
  measurementId: "G-XXXXXXXXXXX"
};

firebase.initializeApp(firebaseConfig);
//secondaryFireApp
// var secondaryFireApp = firebase.initializeApp(firebaseConfig, "Secondary");

// Configure FirebaseUI.
// firebase.auth.EmailAuthProvider.PROVIDER_ID, firebase.auth.GoogleAuthProvider.PROVIDER_ID, firebase.auth.FacebookAuthProvider.PROVIDER_ID
// FirebaseUI config.
const uiConfig = {
  // Popup signin flow rather than redirect flow.
  signInFlow: 'popup',
  signInSuccessUrl: '/',
  signInOptions: [
    {
      provider: firebase.auth.PhoneAuthProvider.PROVIDER_ID,
      recaptchaParameters: {
        type: 'image', // 'audio'
        size: 'invisible', // 'invisible' or 'compact'
        badge: 'bottomleft' //' bottomright' or 'inline' applies to invisible.
      },
      defaultCountry: 'LK',
    },
    {
      provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
      requireDisplayName: false
    },
    {
      provider: firebase.auth.GoogleAuthProvider.PROVIDER_ID
    }
  ],
  // tosUrl and privacyPolicyUrl accept either url string or a callback
  // function.
  // Terms of service url/callback.
  tosUrl: '<your-tos-url>',
  // Privacy policy url/callback.
  privacyPolicyUrl: function () {
    window.location.assign('<your-privacy-policy-url>');
  },
  callbacks: {
    // Avoid redirects after sign-in.
    signInSuccessWithAuthResult: () => true,
    // signInFailure callback must be provided to handle merge conflicts which
    // occur when an existing credential is linked to an anonymous user.
    signInFailure: function (error) {
      console.log("signInFailure :: ", error);
      // For merge conflicts, the error.code will be
      // 'firebaseui/anonymous-upgrade-merge-conflict'.
      if (error.code != 'firebaseui/anonymous-upgrade-merge-conflict') {
        return Promise.resolve();
      }
      // The credential the user tried to sign in with.
      var cred = error.credential;
      // Copy data from anonymous user to permanent user and delete anonymous
      // user.
      // ...
      // Finish sign-in after data is copied.
      return firebase.auth().signInWithCredential(cred);
    }
  }
};

export default class extends React.Component {
  constructor() {
    super();
    this.state = {
      // Framework7 Parameters
      f7params: {
        version: '1.0.0',
        id: 'Org.My-React.WebApp', // App bundle ID
        name: 'My React', // App name
        theme: 'auto', // Automatic theme detection
        // App root data
        data: function () {
          return {
            // Demo products for Catalog section
            products: [
              {
                id: '1',
                title: 'Apple iPhone 8',
                description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi tempora similique reiciendis, error nesciunt vero, blanditiis pariatur dolor, minima sed sapiente rerum, dolorem corrupti hic modi praesentium unde saepe perspiciatis.'
              },
              {
                id: '2',
                title: 'Apple iPhone 8 Plus',
                description: 'Velit odit autem modi saepe ratione totam minus, aperiam, labore quia provident temporibus quasi est ut aliquid blanditiis beatae suscipit odio vel! Nostrum porro sunt sint eveniet maiores, dolorem itaque!'
              },
              {
                id: '3',
                title: 'Apple iPhone X',
                description: 'Expedita sequi perferendis quod illum pariatur aliquam, alias laboriosam! Vero blanditiis placeat, mollitia necessitatibus reprehenderit. Labore dolores amet quos, accusamus earum asperiores officiis assumenda optio architecto quia neque, quae eum.'
              },
            ],
            user: {},
            isSignedIn: false
          };
        },
        // App root methods
        methods: {
          updateFirebaseUser: function (currentUser, rootSelf) {
            // console.log('updateFirebaseUser :: init');
            // console.log('updateFirebaseUser :: rootSelf', rootSelf);
            const self = rootSelf;
            //updateProfile
            currentUser.updateProfile({
              displayName: self.state.userDisplayName,
              photoURL: '../static/icons/128x128.png'
            }).then(function () {
              // Update successful.
            }).catch(function () {
              // An error happened.
            });
          },
          saveLoggedInUser: function (rootSelf) {
            // console.log('saveLoggedInUser :: init');
            // console.log('saveLoggedInUser :: rootSelf', rootSelf);
            const self = rootSelf;
            const isValid = this.input.validateInputs('#userForm');
            if (isValid) {
              this.preloader.show();

              var currentUser = firebase.auth().currentUser;
              var db = firebase.firestore();

              //update firebase user profile
              this.methods.updateFirebaseUser(currentUser, self);

              if (!self.state.userProfile) {
                //create new user in db
                db.collection("users").doc(currentUser.uid).set({
                  userDisplayName: self.state.userDisplayName,
                  userMob: self.state.userMob,
                  userDocument: self.state.userDocument,
                  userAddressLine1: self.state.userAddressLine1,
                  userAddressLine2: self.state.userAddressLine2,
                  userCity: self.state.userCity,
                  userPostalCode: self.state.userPostalCode,
                  userCountry: self.state.userCountry,
                  userPoints: 1000,
                  userGuide: false,
                }).then(function () {
                  self.$f7.preloader.hide();
                  console.log("Document Successfully Written.");
                  self.$f7.dialog.alert("Account Created Successfully.", "Success!", () => {
                    self.$f7.popup.close('#my-popup');
                    self.setState({
                      userProfile: true,
                    });
                    self.$f7.methods.updateAppUser(currentUser, self);
                  });
                }).catch(function (error) {
                  self.$f7.preloader.hide();
                  console.error("Error writing document: ", error);
                  self.$f7.dialog.alert("Error on Account Creation.", "Error!");
                });
              } else {
                //update user in db
                db.collection("users").doc(currentUser.uid).update({
                  userDisplayName: self.state.userDisplayName,
                  userMob: self.state.userMob,
                  userDocument: self.state.userDocument,
                  userAddressLine1: self.state.userAddressLine1,
                  userAddressLine2: self.state.userAddressLine2,
                  userCity: self.state.userCity,
                  userPostalCode: self.state.userPostalCode,
                  userCountry: self.state.userCountry,
                }).then(function () {
                  self.$f7.preloader.hide();
                  console.log("Document Successfully written.");
                  self.$f7.dialog.alert("Account Updated Successfully.", "Success!", () => {
                    self.$f7.popup.close('#my-popup');
                    self.setState({
                      userProfile: true,
                    });
                    self.$f7.methods.updateAppUser(currentUser, self);
                  });
                }).catch(function (error) {
                  self.$f7.preloader.hide();
                  console.error("Error writing document: ", error);
                  self.$f7.dialog.alert("Error on Account Update.", "Error!");
                });
              }
            }
          },
          updateAppUser: function (currentUser, rootSelf) {
            // console.log('updateAppUser :: init');
            // console.log('updateAppUser :: rootSelf', rootSelf);
            const self = rootSelf;
            var db = firebase.firestore();
            //update localStorage
            if (!currentUser) {
              this.data.isSignedIn = false;
              this.data.user = [];
              self.setState({
                isSignedIn: false,
                userProfile: false,
              });
              let requiredLoginToast = this.toast.create({
                text: 'Please sign in.',
                closeTimeout: 3000,
              });
              requiredLoginToast.open();
            } else {
              //get user info from db
              var docRef = db.collection("users").doc(currentUser.uid);
              docRef.get().then(function (doc) {
                if (doc.exists) {
                  var userData = doc.data();
                  console.log("Document data:", userData);
                  self.$f7.data.isSignedIn = true;
                  self.$f7.data.user.displayName = currentUser.displayName;
                  self.$f7.data.user.photoURL = currentUser.photoURL;
                  self.$f7.data.user.phoneNumber = userData.userMob;
                  //tour guide boolean
                  self.$f7.data.user.tourGuide = userData.userGuide;
                  //user info
                  self.$f7.data.user.userDisplayName = userData.userDisplayName;
                  self.$f7.data.user.userMob = userData.userMob;
                  self.$f7.data.user.userDocument = userData.userDocument;
                  self.$f7.data.user.userAddressLine1 = userData.userAddressLine1;
                  self.$f7.data.user.userAddressLine2 = userData.userAddressLine2;
                  self.$f7.data.user.userCity = userData.userCity;
                  self.$f7.data.user.userPostalCode = userData.userPostalCode;
                  self.$f7.data.user.userCountry = userData.userCountry;
                  self.$f7.data.user.userPoints = userData.userPoints;

                  //set States
                  self.setState({
                    isSignedIn: true,
                    userProfile: true,
                    userDisplayName: self.$f7.data.user.userDisplayName,
                    userMob: self.$f7.data.user.userMob,
                    userDocument: self.$f7.data.user.userDocument,
                    userAddressLine1: self.$f7.data.user.userAddressLine1,
                    userAddressLine2: self.$f7.data.user.userAddressLine2,
                    userCity: self.$f7.data.user.userCity,
                    userPostalCode: self.$f7.data.user.userPostalCode,
                    userCountry: self.$f7.data.user.userCountry,
                    userPoints: self.$f7.data.user.userPoints,
                  });

                  let userLoggedInToast = self.$f7.toast.create({
                    text: 'Logged In Successfully.',
                    closeTimeout: 3000,
                  });
                  userLoggedInToast.open();

                  //check user Account Code
                  // if (!userData.userAccountCode) {
                  // self.popup.open('#my-popup');
                  // }
                } else {
                  // doc.data() will be undefined in this case
                  console.log("No such user!");
                }
              }).catch(function (error) {
                console.log("Error getting user:", error);
              });
            }
            this.preloader.hide();
          },
          userLogout: function (rootSelf) {
            console.log('userLogout :: init');
            const self = rootSelf;
            firebase.auth().signOut().then(() => {
              // Sign-out successful.
              var toast_SuccessLogOut = self.$f7.toast.create({
                text: 'Logged Out Successfully.',
                closeTimeout: 3000,
              });
              setTimeout(() => {
                window.location.href = "/";
              }, 3000);
              toast_SuccessLogOut.open();
            }).catch((error) => {
              // Handle Errors here.
              let toast_AppError = self.$f7.toast.create({
                text: 'Connectivity Problem!',
                closeTimeout: 3000,
              });
              toast_AppError.open();
            });
          },
        },
        // App view
        view: {
          pushState: true,
          stackPages: true,
        },
        // App routes
        routes: routes,
        // Register service worker
        serviceWorker: Device.cordova ? {} : {
          path: '/service-worker.js',
        },
        // Input settings
        input: {
          scrollIntoViewOnFocus: Device.cordova && !Device.electron,
          scrollIntoViewCentered: Device.cordova && !Device.electron,
        },
        // Cordova Statusbar settings
        statusbar: {
          iosOverlaysWebView: true,
          androidOverlaysWebView: false,
        },
      },
      // Login screen demo data
      userProfile: false,
      userGuide: false,
      userDisplayName: '',
      userMob: '',
      userDocument: '',
      userEmail: '',
      userAddressLine1: '',
      userAddressLine2: '',
      userCity: '',
      userPostalCode: '',
      userCountry: '',
      userPoints: 0,
    }
  }
  render() {
    return (
      <App params={this.state.f7params} >

        {/* Left panel with cover effect*/}
        <Panel left cover themeDark>
          <View>
            <Page>
              <Navbar title="Left Panel" />
              <Block>Left panel content goes here</Block>
            </Page>
          </View>
        </Panel>

        {/* Right panel with reveal effect*/}
        <Panel right reveal>
          <View>
            <Page>
              <Navbar title={this.state.isSignedIn ? firebase.auth().currentUser.displayName !== null ? firebase.auth().currentUser.displayName : 'My Account' : 'Login'} />
              {/* Toolbar */}
              <Toolbar bottom>
                <Link className="width-100">All Rights Reserved</Link>
              </Toolbar>
              {
                this.state.isSignedIn ? (
                  <Block>
                    <p>Welcome, {firebase.auth().currentUser.displayName} ! You are now signed-in.</p>
                    <List>
                      <ListItem link="/settings/" title="Settings" view=".view-main" panelClose>
                        <Icon slot="media" f7="gear_alt" color="primary"></Icon>
                      </ListItem>
                      <ListItem link="#" title="Logout" onClick={() => this.$f7.methods.userLogout(this)} view=".view-main" panelClose>
                        <Icon slot="media" f7="power" color="primary"></Icon>
                      </ListItem>
                    </List>
                  </Block>
                ) : (
                    <Block>
                      <p>Please login to your account.</p>
                      <List>
                        <ListItem link="#" title="Login" loginScreenOpen="#my-login-screen" panelClose>
                          <Icon slot="media" f7="person" color="primary"></Icon>
                        </ListItem>
                      </List>
                    </Block>
                  )
              }
            </Page>
          </View>
        </Panel>

        {/* Your main view, should have "view-main" class */}
        <View main className="safe-areas" url="/" />

        {/* Popup */}
        <Popup id="my-popup">
          <View>
            <Page>
              <Navbar title="My Account">
                {
                  <NavRight>
                    {this.state.userProfile ? <Link popupClose iconF7="xmark_circle"></Link> : ''}
                  </NavRight>
                }
              </Navbar>
              <BlockTitle>Update Your Account</BlockTitle>
              <Block noHairlines>
                <List form id="userForm">
                  <ListInput
                    label="Display Name"
                    type="text"
                    placeholder="Jemmy Jackson"
                    inputId="userDisplayName"
                    defaultValue={this.state.userDisplayName}
                    onInput={(e) => this.setState({ userDisplayName: e.target.value })}
                    required
                    validate
                  ></ListInput>
                  <ListInput
                    label="Mobile"
                    type="tel"
                    placeholder="0716576789"
                    inputId="userMob"
                    disabled
                    value={this.state.userMob}
                    onInput={(e) => this.setState({ userMob: e.target.value })}
                    required
                    validate
                  ></ListInput>
                  <ListInput
                    label="NIC / Passport"
                    type="text"
                    placeholder="896785142V"
                    inputId="userDocument"
                    minlength="10"
                    maxlength="13"
                    defaultValue={this.state.userDocument}
                    onInput={(e) => this.setState({ userDocument: e.target.value })}
                  // required
                  // validate
                  ></ListInput>
                  <ListInput
                    inputId="userAddressLine1"
                    defaultValue={this.state.userAddressLine1}
                    onInput={(e) => this.setState({ userAddressLine1: e.target.value })}
                    label="Address Line 1"
                    type="text"
                    placeholder="477"
                    required
                    validate
                  ></ListInput>
                  <ListInput
                    inputId="userAddressLine2"
                    defaultValue={this.state.userAddressLine2}
                    onInput={(e) => this.setState({ userAddressLine2: e.target.value })}
                    label="Address Line 2" type="text"
                    placeholder="Flower Park Road, Kattuwa"
                  // required
                  // validate
                  ></ListInput>
                  <ListInput
                    inputId="userCity"
                    defaultValue={this.state.userCity}
                    onInput={(e) => this.setState({ userCity: e.target.value })}
                    label="City"
                    type="text"
                    placeholder="Negombo"
                    required validate
                  ></ListInput>
                  <ListInput
                    inputId="userPostalCode"
                    defaultValue={this.state.userPostalCode}
                    onInput={(e) => this.setState({ userPostalCode: e.target.value })}
                    label="Postal Code"
                    type="text"
                    placeholder="11500"
                  // required
                  // validate
                  ></ListInput>
                  <ListInput
                    inputId="userCountry"
                    defaultValue={this.state.userCountry}
                    onInput={(e) => this.setState({ userCountry: e.target.value })}
                    label="Country"
                    type="text"
                    placeholder="Sri Lanka"
                  // required 
                  // validate
                  ></ListInput>
                </List>
                <Button text={this.state.userProfile ? 'Update' : 'Save'} className="width-100" fill raised round onClick={() => this.$f7.methods.saveLoggedInUser(this)} ></Button>
              </Block>
            </Page>
          </View>
        </Popup>

        <LoginScreen id="my-login-screen">
          <View>
            <Page loginScreen>
              <List form>
                <StyledFirebaseAuth uiConfig={uiConfig} firebaseAuth={firebase.auth()} />
              </List>
            </Page>
          </View>
        </LoginScreen>
      </App>
    )
  }
  onPanelBreakpoint() {
    // console.log('App - onPanelBreakpoint :: init');
    const self = this;
  }
  alertLoginData() {
    this.$f7.dialog.alert('Username: ' + this.state.username + '<br>Password: ' + this.state.password, () => {
      this.$f7.loginScreen.close();
    });
  }
  componentWillUnmount() {
    // console.log('App - componentWillUnmount :: init');
    // Make sure we un-register Firebase observers when the component unmounts.
    this.unregisterAuthObserver();
  }
  componentDidMount() {
    // console.log('App - componentDidMount :: init');
    const self = this;
    this.$f7.preloader.show();
    this.unregisterAuthObserver = firebase.auth().onAuthStateChanged(user => {
      var theUser;
      if (user) {
        // User is signed in.
        theUser = user;
        console.log('onAuthStateChanged :: login', theUser);

        //set phoneNumber
        this.setState({
          userMob: theUser.phoneNumber,
        });

        if (!theUser.displayName) {
          this.$f7.popup.open('#my-popup');
          this.$f7.preloader.hide();
        } else {
          this.$f7.methods.updateAppUser(theUser, self);
        }

        // localStorage.setItem('userInfo', JSON.stringify(this.$f7.data.user));
        // let userInfo = JSON.parse(localStorage.getItem("userInfo"));
        // console.log("userInfo :: ", userInfo);

        // this.$f7.preloader.hide();
      } else {
        // No user is signed in.
        theUser = null;
        console.log('onAuthStateChanged :: no-login');

        this.$f7.methods.updateAppUser(theUser, self);

        // localStorage.setItem('userInfo', JSON.stringify(this.$f7.data.user));
        // let userInfo = JSON.parse(localStorage.getItem("userInfo"));
        // console.log("userInfo :: ", userInfo);

        // this.$f7.preloader.hide();
      }
      console.log("onAuthStateChanged :: data :: ", this.$f7.data);
    });
    //
    this.$f7ready((f7) => {
      // Call F7 APIs here
    });
  }
}

Required below dependencies.

"dependencies": {
        "dom7": "^2.1.5",
        "firebase": "^7.24.0",
        "framework7": "^5.7.14",
        "framework7-icons": "^3.0.1",
        "framework7-react": "^5.7.14",
        "prop-types": "^15.7.2",
        "react": "^16.14.0",
        "react-dom": "^16.14.0",
        "react-firebaseui": "^4.1.0",
        "react-joyride": "^2.2.1",
        "template7": "^1.4.2"
    },

Update accordingly. Happy Coding!