DEV Community

Cover image for Firebase Auth with React Hooks in Typescript
Benjamin
Benjamin

Posted on • Edited on

Firebase Auth with React Hooks in Typescript

Overview

Firebase is a great provider for hooking up easy and simple authentication to a new or existing project, and can easily be integrated with other features of Google Cloud Platform. Adding it to your application can be simple, but a lot of tutorials don't cater for larger scale applications, and how it could be implemented cleanly and with quality assurance in mind.

Assumed Knowledge

  • Firebase
  • Typescript
  • React
  • React Hooks (specifically useContext)

Setting Up

GCP and Firebase

To start, you'll need to setup a GCP account and login to the Firebase console at https://console.firebase.google.com/. You'll then need to setup a project for us to use in this run through. For this walkthrough, I've named my project "HooksAuth"

I'm then going to enable email/password and Google Authentication by navigating to the "Authentication" page from the left menu and enabling them there

React

To setup your react project from scratch, you can use create-react-app by running the following command in your cli: npx create-react-app hooksAuth --template typescript

The next (optional) step is to remove all the boilerpate content from your React App. e.g. react images, manifest, App.tsx content etc. This helps me to start from a cleaner slate and not have create-react-app content in my site

Setting up the hooks

We are going to abstract our firebase app away through useContext so it's state can be shared through the app, and any abstractions and access can easily be updated and refactored.

  • Create FirebaseContext.ts
  • Add your config to this file (this can be retrieved by registering a web app in the firebase console), and will look something like:
import firebase from 'firebase';

const firebaseConfig = {
    apiKey: "KEY",
    authDomain: "somedomain.firebaseapp.com",
    databaseURL: "https://somedomain.firebaseio.com",
    projectId: "hooksauth-ID_HERE",
    storageBucket: "hooksauth-ID_HERE.appspot.com",
    messagingSenderId: "SENDER_ID",
    appId: "APP_ID"
  };
  // Initialize Firebase
  firebase.initializeApp(firebaseConfig);
Enter fullscreen mode Exit fullscreen mode
  • Now we want to secure these values using .env (before we accidentally commit anything). To do this, create a file called .env.local in the root of the project, and add this file to .gitignore. In that file, you'll want to define your ID's in something similar to this format:
REACT_APP_API_KEY=KEY
REACT_APP_AUTH_DOMAIN=somedomain.firebaseapp.com
REACT_APP_DB_URL=https://somedomain.firebaseio.com
REACT_APP_PROJECT_ID=hooksauth-ID_HERE
REACT_APP_STORAGE_BUCKET=hooksauth-ID_HERE.appspot.com
REACT_APP_MESSAGING_SENDER_ID=SENDER_ID
REACT_APP_APP_ID=APP_ID
Enter fullscreen mode Exit fullscreen mode

and update your config to be:

const firebaseConfig = {
    apiKey: process.env.REACT_APP_API_KEY,
    authDomain: process.env.REACT_APP_AUTH_DOMAIN,
    databaseURL: process.env.REACT_APP_DB_URL,
    projectId: process.env.REACT_APP_PROJECT_ID,
    storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
    messagingSenderId: process.env.REACT_APP_MESSAGING_SENDER_ID,
    appId: process.env.REACT_APP_APP_ID,
};
Enter fullscreen mode Exit fullscreen mode
  • Move the firebase initialisation. To stop the firebase initialisation happening multiple times, we want to wrap it in an if statement to make it look like:
// Initialize Firebase
if (!firebase.apps.length) {
    firebase.initializeApp(firebaseConfig);
    firebase.analytics();
}
Enter fullscreen mode Exit fullscreen mode
  • Now we want to actually do some React stuff. We want to create a context for us to use in the rest of our app. So using react hooks, we will create a context that contains the auth providers we will use, and a way to access our firebase object:
export interface IFirebaseContext {
    firebase: firebase.app.App,
    authProviders: string[]
}

export const FirebaseContext = React.createContext({} as IFirebaseContext)
Enter fullscreen mode Exit fullscreen mode

And then our provider to wrap the app:

export const FirebaseProvider = ({ children }: any) => {
    return (
        <div>
            <FirebaseContext.Provider value={{ 'firebase': firebase.app(), authProviders } as IFirebaseContext}>
                {children}
            </FirebaseContext.Provider>
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode
  • Now to wrap the rest of our app. So in App.tsx, we want to wrap the root div in <FirebaseProvider>. And now in the rest of our App, if we want to access our auth object, we would simply call const firebaseContext = useContext(FirebaseContext); and access it there. This can be combined with the firebase-ui package to get your authentication up and running in no time

For an example of usage with the react-firebaseui package and saving user data see my github repo: https://github.com/bmpickford/firebase-auth-example

Open to any improvements so feel free to submit a PR or an issue

Top comments (4)

Collapse
 
jivkojelev91 profile image
JivkoJelev91

Nice article, thank u

Collapse
 
bmpickford profile image
Benjamin

Thanks for the feedback :) I'll try to get around to putting up an example this week sometime!

Collapse
 
jesperbylund profile image
JesperBylund

This is a really awesome starter! Would be good to see an example of using the provider tho.

Collapse
 
ampex profile image
Ampex

Thanks for sharing this. Could you provide a sandbox or something ?