Connor Deane
Connor Deane

Reputation: 73

db.collection is not a function React / Firestore

Trying to implement Firestore into a LinkedIn clone using React. I believe the new way of importing Firebase/firestore is as follows.

firebase.js

import {initializeApp} from 'firebase/app';
import { getFirestore } from 'firebase/firestore';

I've then initialized the firebase config and created a const db.

firebase.js

const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
 

export {db}

The problem I am having is on my 'Feed.js' file I am trying to run a collection function from firestore but receiving an error.

feed.js

useEffect(() => {
db.collection('posts').onSnapshot(snapshot => (
    setPosts(snapshot.docs.map(doc =>(
        {
            id: doc.id,
            data: doc.data()
        }
    )))
))
},[])

db is imported on feed.js

import { db } from './firebase';

Is there an updated way of writing this?

Upvotes: 1

Views: 1797

Answers (3)

Connor Deane
Connor Deane

Reputation: 73

The solution that worked for me.

useEffect(() =>{
    const newPost = onSnapshot(collection(db, 'posts'), (snapshot) =>{
    setPosts(snapshot.docs.map(doc => ({...doc.data(), id: doc.id})));
    });
    return newPost
}, []);

Thanks @Frank van Puffelen

Upvotes: 2

samthecodingman
samthecodingman

Reputation: 26296

In the new modular SDK, majority of the API surface has changed. There's documentation on how to migrate code from the old namespaced SDK here.

Most of the relevant Firestore exports that you will use are listed here. In particular, you need to use the exported collection and onSnapshot functions to replace Firestore#collection() and CollectionReference#onSnapshot().

import { initializeApp } from 'firebase/app';
import { getFirestore, collection, onSnapshot } from 'firebase/firestore';

const app = initializeApp(firebaseConfig);
const db = getFirestore(app);

useEffect(() => {
  const colRef = collection(db, 'posts');

  const unsubListener = onSnapshot(colRef, snapshot => {
    setPosts(snapshot.docs.map(doc => ({
      id: doc.id,
      data: doc.data()
    })));
  });

  return unsubListener; // <- don't forget to return the unsubscribe function!
},[]);

I recommend using the observer version of onSnapshot so that you can handle errors gracefully and improve the readability of your code.

useEffect(() => {
  const colRef = collection(db, 'posts');

  const unsubListener = onSnapshot(colRef, {
    next: (snapshot) => {
      setPosts(snapshot.docs.map(doc => ({
        id: doc.id,
        data: doc.data()
      })));
    },
    error: (err) => {
      // TODO: handle error (signed out? no permission? no connection?)
    }
  });

  return unsubListener; // <- don't forget to return the unsubscribe function!
},[]);

Upvotes: 1

Frank van Puffelen
Frank van Puffelen

Reputation: 600081

That should be something like this:

onSnapshot(collection(db, 'posts'), (snapshot) => {
    setPosts(snapshot.docs.map((doc) => {
        return {
            id: doc.id,
            data: doc.data()
        }
    })
})

I highly recommend checking out the documentation on upgradeing from version 8 to the modular Web SDK and the code samples in the documentation on reading from Firestore, as it's unlikely we can rewrite all your code for you like this.

Upvotes: 0

Related Questions