Using Firebase with Gatsby

FirebaseTipsReactGatsby

I struggled a lot with this because you don’t have the window object when trying to initialize firebase, so every post I found in how to solve it propones to create a method to check if it was initialized and save the instance to a variable.

I don’t like that, I just want to use it without caring if I have to initialize it or not.

This is how I solved it:

import firebase from "firebase/app";

import "firebase/auth";
import "firebase/firestore";

export default new Proxy(
  {
    get database() {
      return firebase.firestore();
    },
    get auth() {
      return firebase.auth();
    },
    providers: {
      get google() {
        return new firebase.auth.GoogleAuthProvider();
      },
    },
  },
  {
    get: function(target, name) {
      if (!firebase.apps.length) {
        firebase.initializeApp({
          apiKey: process.env.GATSBY_API_KEY,
          authDomain: process.env.GATSBY_AUTH_DOMAIN,
          databaseURL: process.env.GATSBY_DATABASE_URL,
          projectId: process.env.GATSBY_PROJECT_ID,
          storageBucket: process.env.GATSBY_STORAGE_BUCKET,
          messagingSenderId: process.env.GATSBY_MESSAGING_SENDER_ID,
          appId: process.env.GATSBY_APP_ID,
        });
      }

      return target[name];
    },
  }
);

This way we always check if firebase is initialized without the need of doing it explicitly, just be sure to have the window object when you call a method.

Example of use:

import firebase from "../firebase";
import { IUser } from "../session";

import { ITodo } from "./types";

export default {
  add: (user: IUser["uid"], todo: Partial<ITodo>) =>
    firebase.database
      .collection("users")
      .doc(user)
      .collection("todos")
      .add(todo),
  update: (user: IUser["uid"], todo: ITodo) =>
    firebase.database
      .collection("users")
      .doc(user)
      .collection("todos")
      .doc(todo.id)
      .update(todo),
  remove: (user: IUser["uid"], id: ITodo["id"]) =>
    firebase.database
      .collection("users")
      .doc(user)
      .collection("todos")
      .doc(id)
      .delete(),
  onChange: (user: IUser["uid"], callback: (todos: ITodo[]) => void) =>
    firebase.database
      .collection("users")
      .doc(user)
      .collection("todos")
      .onSnapshot(snapshot => callback(snapshot.docs.map(doc => ({ id: doc.id, ...(doc.data() as ITodo) })))),
};

You can find the full repo where this is being used in here: https://github.com/goncy/typescript-firebase-context-gatsby-todos

goncy

goncy

Frontend Developer @Vercel | Cypress.io Ambassador

Read More