2

I'm working with Firebase and initializing the APIs and functions to retrieve data I need in firebase.tsx and then importing them in my pages/index.tsx file but can't access exports after Firebase app initilization

services/firebase.tsx:

import firebase, { FirebaseOptions } from 'firebase/app'
import { getAuth } from 'firebase/auth';
import { collection, doc, setDoc, getFirestore, query, where, getDocs, orderBy } from "firebase/firestore";
import { getStorage } from 'firebase/storage';
import { getAnalytics } from "firebase/analytics";

import config from '../config';

import Blog, { blogConverter } from "../models/Blog";

export const yo = 'yo'

if (!firebase.getApps().length) {
    firebase.initializeApp(config.firebaseConfig as FirebaseOptions);
}

export const auth = getAuth();
export const firestore = getFirestore();
export const storage = getStorage();
export const analytics = getAnalytics();

/**
 * Get all blogs from firebase
 * @returns {Promise<Blog[]>} A promise that resolves to an array of Blog objects
 */
export const getBlogs = async (): Promise<Blog[]> => {
    const q = query(
        collection(firestore, "blogs"),
        where("status", "==", "published"),
        where("publish_date", "<", new Date().toUTCString()),
        orderBy("publish_date", "desc")
    ).withConverter(blogConverter);

    const querySnapshot = await getDocs(q);
    if (querySnapshot.empty) return [];

    const allBlogs: Blog[] = querySnapshot.docs.map(doc => doc.data());
    return allBlogs;
}

pages/index.tsx

import type { NextPage } from 'next'
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
import { GetServerSideProps } from 'next'
import { getBlogs, yo } from '../services/firebase'

import Link from 'next/link'

import Blog from '../models/Blog'

export const getServerSideProps: GetServerSideProps = async (context) => {
  console.log(yo)

  const blogs = await getBlogs()
  return {
    props: {
      blogs
    }
  }
}

interface Props {
  blogs: Blog[]
}

const Home: NextPage<Props> = ({ blogs }) => {
...
}

When I move export const yo = 'yo' after line 15, I get a "cannot access 'yo' before initialization but with where it is now I do not.

It seems like initializing Firebase is delaying the initialization of exports to come after it but I have seen other people follow this same pattern?

What am I missing?

Error Message error

Gourav B
  • 864
  • 5
  • 17
Leo
  • 76
  • 1
  • 7
  • Can you share the screenshot of the error message? Also edit the question and add code of ../services/firebase – Priyashree Bhadra Jan 14 '22 at 10:59
  • Also what is the version of Firebase SDK you are using? – Priyashree Bhadra Jan 14 '22 at 11:22
  • @PriyashreeBhadra Hi sorry I previously named the code block lib/firebase that was referring to services/firebase. I corrected the name and attached a screenshot of the error. getBlogs is defined after the firebase initialization. Im using firebase 9.6.3 – Leo Jan 14 '22 at 23:04
  • 1
    @PriyashreeBhadra i solved it by switching to /compat imports seeing this question: https://stackoverflow.com/questions/69076827/cannot-read-properties-of-undefined-reading-app and as described here https://firebase.google.com/docs/web/modular-upgrade. seems like something bugger with version 9 module imports? – Leo Jan 14 '22 at 23:55
  • great!! I have posted an answer explaining why the imports syntax become a little different in case we use Firebase Javascript SDK version 9 and above. Also this is not something bugger but just a [feature release in version 9s](https://firebase.google.com/support/release-notes/js#version_900_-_august_25_2021). If you feel my answer was informative and helped you in any way kindly upvote/accept the answer. Thanks and have a great day ahead! – Priyashree Bhadra Jan 17 '22 at 08:06

2 Answers2

0

Firebase JavaScript SDK (>= v 9.0) introduces the new modular API, and includes breaking changes. If you are using v8 you need to update your code in order for it to still work with version 9.0.0 and higher. Though the majority of the version 9 SDK follows the same patterns as version 8, the organization of the code is different. So it's definitely not a bugger with version 9 imports but rather a new way of having the imports.

For example, version 8's dot-chaining, such as firebaseApp.auth(), is replaced in version 9 by a single getAuth() function that takes firebaseApp and returns an Authentication instance. This means that Web apps created with version 8 or earlier require refactoring in order to take advantage of version 9's modular approach. Firebase provides compat libraries to ease that transition in v9. As you said, you have to update your imports

From

Before: version 8

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

To

After: version 9 compat

// v9 compat packages are API compatible with v8 code
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
 

Also you can refactor your code as per modular style which is again a little different from the compat version. All this is documented here. Go through it to have a clear understanding of the differences.

Priyashree Bhadra
  • 3,182
  • 6
  • 23
0

Also, please be advised on below as mentioned here.

Keep in mind: the compat libraries are a temporary solution that will be removed completely in a future major SDK version (such as version 10 or version 11). Your ultimate goal is to remove compat code and keep only version 9 modular-style code in your app.

So, "compat" is just a temporary solution to get your v8 code working with v9 without much rework. Eventually, you need to refactor code to modular style.

Gourav B
  • 864
  • 5
  • 17