How to solve FirebaseError: Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore problem?

Viewed 17996

I am trying to set up Firebase with next.js. I am getting this error in the console.

FirebaseError: Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore

This is one of my custom hook

import { onAuthStateChanged, User } from '@firebase/auth'
import { doc, onSnapshot, Unsubscribe } from 'firebase/firestore'
import { useEffect, useState } from 'react'
import { auth, fireStore } from './firebase'

export const useUserData = () => {
  const [username, setUsername] = useState<string | null>(null)

  const [currentUser, setCurrentUser] = useState<User | null>(null)

  useEffect(() => {
    let unsubscribe: void | Unsubscribe

    onAuthStateChanged(auth, (user) => {
      if (user) {
        setCurrentUser(user)
        // The Problem is inside this try blog
        try {
          // the onsnapshot function is causing the problem
          console.log('firestore: ', fireStore)
          unsubscribe = onSnapshot(doc(fireStore, 'users', user.uid), (doc) => {
            setUsername(doc.data()?.username)
          })
        } catch (e) {
          console.log(e.message)
        }
      } else {
        setCurrentUser(null)
        setUsername(null)
      }
    })

    return unsubscribe
  }, [currentUser])

  return { currentUser, username }
}

I also have this firebase.ts file where I initialized my firebase app

import { FirebaseApp, getApps, initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'
import { getFirestore } from 'firebase/firestore/lite'
import { getStorage } from 'firebase/storage'

const firebaseConfig = {
  apiKey: 'some-api',
  authDomain: 'some-auth-domain',
  projectId: 'some-project-id',
  storageBucket: 'some-storage-bucket',
  messagingSenderId: 'some-id',
  appId: 'some-app-id',
  measurementId: 'some-measurement-id',
}

let firebaseApp: FirebaseApp

if (!getApps.length) {
  firebaseApp = initializeApp(firebaseConfig)
}

const fireStore = getFirestore(firebaseApp)
const auth = getAuth(firebaseApp)
const storage = getStorage(firebaseApp)

export { fireStore, auth, storage }

I don't know whether the problem is in the project initialization. I am pretty sure the error is generated from my custom hook file. I also found out that there must be something wrong with onSnapshot function. Am I passing the docRef wrong or something? What am I doing wrong here?

The console.log(firestore) log:


    type: "firestore-lite"
    _app: FirebaseAppImpl
    _automaticDataCollectionEnabled: false
    _config: {name: "[DEFAULT]", automaticDataCollectionEnabled: false}
    _container: ComponentContainer {name: "[DEFAULT]", providers: Map(15)}
    _isDeleted: false
    _name: "[DEFAULT]"
    _options:
    apiKey: 'some-api'
    authDomain: 'some-auth-domain'
    projectId: 'some-project-id'
    storageBucket: 'some-storage-bucket'
    messagingSenderId: 'some-id'
    appId: 'some-app-id'
    measurementId: 'some-measurement-id'
    [[Prototype]]: Object
    automaticDataCollectionEnabled: (...)
    config: (...)
    container: (...)
    isDeleted: (...)
    name: (...)
    options: (...)
    [[Prototype]]: Object
    _credentials: Q {auth: AuthInterop}
    _databaseId: H {projectId: "next-firebase-fireship", database: "(default)"}
    _persistenceKey: "(lite)"
    _settings: ee {host: "firestore.googleapis.com", ssl: true, credentials: undefined, ignoreUndefinedProperties: false, cacheSizeBytes: 41943040, …}
    _settingsFrozen: false
    app: (...)
    _initialized: (...)
    _terminated: (...)

5 Answers

Using getFirestore from lite library will not work with onSnapshot. You are importing getFirestore from lite version:

import { getFirestore } from 'firebase/firestore/lite'

Change the import to:

import { getFirestore } from 'firebase/firestore'

From the documentation,

The onSnapshot method and DocumentChange, SnapshotListenerOptions, SnapshotMetadata, SnapshotOptions and Unsubscribe objects are not included in lite version.


Another reason for this error to show up could be passing invalid first argument to collection() or doc() functions. They both take a Firestore instance as first argument.

// Ensure that "db" is defined and initialized
const db = getFirestore();
// console.log(db);

const colRef = collection(db, "collection_name");

Don't mix usage of firestore/lite with firestore

You need to use in your imports either:

'firebase/firestore'

OR

'firebase/firestore/lite'

Not both in the same project.

In your case, the firebase.ts file is using:

import { getFirestore } from 'firebase/firestore/lite'

And in your hook:

import { doc, onSnapshot, Unsubscribe } from 'firebase/firestore'

So you're initialising the lite but using the full version afterwards.

Keep in mind that both has it's benefits, but I would suggest in your case to pick one and just use it. Then the error will be gone.

Adding to @Dharmaraj, if you are using firebase react hooks, use the reverse.

Instead of

import { getFirestore } from 'firebase/firestore'

Use

import { getFirestore } from 'firebase/firestore/lite'

If you are using firebase lite then collection is not used.

Firebase lite example:

import {
 getFirestore,
 getDoc,
 updateDoc,
 doc
} from '@firebase/firestore/lite';

const firestore = getFirestore(app);
const docRef = doc(firestore, 'collection/doc');
const docSnap = await getDoc(docRef);
await updateDoc(docRef, "field", 'value');

When to use Firestore Lite
It can be tricky to decide when to let go of the standard Firestore SDK's offline persistence and caching features. You should understand these features before deciding to trade them away for the lower overhead of Firestore Lite. In general, weigh these factors when deciding whether to use Firestore Lite:

  1. Online status - Firestore Lite is good for apps that do not need live updates and have connectivity.
  2. Size constraints - Firestore Lite is great if you want to reduce your overall JavaScript bundle size.

Read more here

This can happen if you have both @firebase/firestore and firebase installed and there is a version mismatch.

firebase comes with @firebase/firestore. Remove any @firebase/... dependencies so that you're using the same version that firebase uses.

Related