I am using NextJS and Firebase fairly new to both. My app is trying to collect data from firestore database on some occasions it works fine and sometimes it returns "n is undefined" refering to the firestore object "db". This happens when i call the "collection(db, "users", uid, "posts")" function in the [posts].js file. What is causing this?
Firebase.js
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import {getStorage} from "firebase/storage"
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "xxxxxxxxxxxxxxxxxxxxxxxxx",
projectId: "xxxxxxxxxxxxxxxxxxxx",
storageBucket: "xxxxxxxxxxxxxxxxxxxx",
messagingSenderId: "xxxxxxxxxxxxxxxx",
appId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const storage = getStorage(app);
export const db = getFirestore(app);
[posts].js
import { useRouter } from 'next/router'
import { useState, useEffect } from 'react';
import Link from 'next/link';
import { useAuth } from '../context/AuthContext'
import styles from '../styles/dashboard.module.css';
import Image from 'next/image';
import { collection, getDocs } from "firebase/firestore";
import { db } from '../lib/firebase';
export default function Posts(){
const [queriedData, setQueriedData] = useState([]);
const router = useRouter()
const { uid } = router.query
useEffect(() => {
async function fetchData() {
const postsRef = collection(db, "users", uid, "posts");
const snapshot = await getDocs(postsRef);
const postData = snapshot.docs.map((doc) => {
const data = doc.data();
data.id = doc.id;
return data;
});
setQueriedData(postData);
}
fetchData();
}, []);
return(
{queriedData.map((post) =>(<div>post.title</div>)
)}
}
Added await to the collection function and I also thought it was internet issues hence i setup a firebase emulator still got the same behavior.
I tried console logging "db" right after the line "export const db = getFirestore(app);". I got out "[Object Object]"
Related
The NextJS app was working fine a few days ago and now giving the following error. Nothing has changed in backend and table still exists.
Unhandled Runtime Error
FirebaseError: Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore
My firebase config file
import { initializeApp, getApp, getApps } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
import { getStorage } from 'firebase/storage';
const firebaseConfig = {
apiKey: XXX,
authDomain: XXX,
projectId: XXX,
storageBucket: XXX,
messagingSenderId: XXX,
appId: XXX,
measurementId: XXX,
};
const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();
const auth = getAuth(app);
const db = getFirestore(app);
const storage = getStorage(app);
export { app, auth, db, storage };
And the useEffect inside the function component
import React, { useEffect, useState } from "react";
import {
onSnapshot,
collection,
addDoc,
getDocs,
orderBy,
query,
where,
limit,
QuerySnapshot,
} from "firebase/firestore";
import { db } from "../../config/firebase";
const [users, setUsers] = useState([]);
useEffect(() => {
const q = query(
collection(db, "user_info"),
orderBy("name", "asc")
);
getDocs(q).then((querySnapshot) => {
const docs = [];
querySnapshot.forEach((doc) => {
docs.push(doc.data());
});
setUsers(docs);
});
}, []);
Also, tried using #useCollectionData from 'react-firebase-hooks', however, the same error happens.
#This works
console.log(db)
const myCollectionRef = collection(db, 'users');
const myCollectionQuery = query(myCollectionRef);
const [users, reactloading, reacterror] = useCollectionData(myCollectionQuery);
#This does not
console.log('users',users)
Seems like the app works fine as in getting data in the pages at root level, however, the firestore collection and query function breaks if used in the nested route.
I've been getting this error working on react-native. Firebase connects normally, with auth(), but I can't seem to get it working for firestore. The problem only occurred on Android Emulator, the iOS one is working fine.
error only occurred on Android Virtual Device, the iOS one work perfectly
Here is Firebase file (removed some information about the app)
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: '',
authDomain: '',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: '',
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth();
const db = getFirestore(app);
export { auth, db };
Here is where I used Firestore function
import React, { useState } from 'react';
import { useTailwind } from 'tailwind-rn/dist';
import useAuth from '../../hooks/useAuth';
import { doc, serverTimestamp, setDoc } from 'firebase/firestore';
import { db } from '../../Firebase';
import { useNavigation } from '#react-navigation/native';
const ModalScreen = () => {
const tw = useTailwind();
const [image, setImage] = useState('');
const [job, setJob] = useState('');
const [age, setAge] = useState('');
const navigation = useNavigation();
const inCompleteForm = !image || !job || !age;
const updateUserProfile = () => {
setDoc(doc(db, 'users', user.uid), {
id: user.uid,
displayName: user.displayName,
photoURL: image,
job,
age,
timestamp: serverTimestamp(),
})
.then(() => {
navigation.navigate('Home');
})
.catch(err => {
alert(err.message);
});
};
import {
View,
Text,
SafeAreaView,
TouchableOpacity,
Image,
StyleSheet,
Platform,
} from 'react-native';
import React, { useRef, useState, useLayoutEffect } from 'react';
import { useTailwind } from 'tailwind-rn/dist';
import { useNavigation } from '#react-navigation/native';
import useAuth from '../../hooks/useAuth';
import Icon from 'react-native-vector-icons/Ionicons';
import Swiper from 'react-native-deck-swiper';
import { doc, onSnapshot } from 'firebase/firestore';
import { db } from '../../Firebase';
const HomeScreen = () => {
const navigation = useNavigation();
const tw = useTailwind();
const [profiles, setProfiles] = useState([]);
const { user, logOut } = useAuth();
const swipeRef = useRef(null);
useLayoutEffect(() => {
onSnapshot(doc(db, 'users', user.uid), snapshot => {
if (!snapshot.exists) navigation.navigate('Modal');
});
}, []);
Error
[2022-03-15T06:49:42.961Z] #firebase/firestore: Firestore (9.6.8): Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds.
This typically indicates that your device does not have a healthy Internet connection at the moment. The client will operate in offline mode until it is able to successfully connect to the backend.
WARN [2022-03-15T06:53:06.868Z] #firebase/firestore: Firestore (9.6.8): Connection WebChannel transport errored: {"defaultPrevented": false,
i got the same problem, try to see here or the code i will give bellow if it can solve the problem :)
import { initializeFirestore } from 'firebase/firestore'
const database = initializeFirestore(app, {
experimentalAutoDetectLongPolling: true
})
const "database" in my example is not the same as "db" in your code, keep the both
It may be a fundamental concept but I can't find anything to my issue.
const userDoc = getUserWithUID(auth.currentUser.uid);
Cannot read property 'uid' of null
import ImageUploader from "../components/ImageUploader";
import {auth, getUserWithUID, postToJSON} from "../lib/firebase";
import {useContext} from "react";
import {UserContext} from "../lib/context";
export async function getServerSideProps(context) {
const userDoc = getUserWithUID(auth.currentUser.uid);
return {props: {userDoc}} ;
}
export default function SettingsPage() {
return (
<main>
<ImageUploader></ImageUploader>
</main>
)
/ Firebase lib file
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import 'firebase/storage';
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_API_KEY,
authDomain: process.env.NEXT_PUBLIC_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_APP_ID,
measurementId: process.env.NEXT_PUBLIC_MEASUREMENT_ID
};
if(!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
export const auth = firebase.auth();
export const googleAuthProvider = new firebase.auth.GoogleAuthProvider();
export const firestore = firebase.firestore();
// Storage exports
export const storage = firebase.storage();
export const STATE_CHANGED = firebase.storage.TaskEvent.STATE_CHANGED;
export const fromMillis = firebase.firestore.Timestamp.fromMillis;
export const serverTimestamp = firebase.firestore.FieldValue.serverTimestamp;
/**`
* Gets a users/{uid} document with company
* #param {string} company
*/
export async function getUserWithCompany(company) {
const usersRef = firestore.collection('users');
const query = usersRef.where('company', '==', company).limit(1);
const userDoc = (await query.get()).docs[0];
return userDoc;
}
export async function getUserWithUID(uid) {
const userDoc = await firestore.collection('users').doc(uid).get();
return userDoc;
}
As far as my understanding goes, getServerSideProps() is only executed on the server and therefore has no access to frontEnd Data such as the Google authentication token and the corresponding userID. Hope this helps, even though you asked one month ago. :)
Not sure why I am getting this error, here's my setup. this error only happens for firestore. Auth, functions, storage, realtimedb work not sure what I'm missing. I followed The firebase documentation to set up.
firebase.js
import { initializeApp } from "firebase/app";
import { initializeAppCheck, ReCaptchaV3Provider } from "firebase/app-check";
import { getDatabase, connectDatabaseEmulator } from "firebase/database";
import {
getAuth,
connectAuthEmulator,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
} from "firebase/auth";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
import {
getFunctions,
connectFunctionsEmulator,
httpsCallable,
} from "firebase/functions";
import { getStorage, connectStorageEmulator } from "firebase/storage";
import Constants from "expo-constants";
// Initialize Firebase
const firebaseConfig = {
apiKey: Constants.manifest.extra.apiKey,
authDomain: Constants.manifest.extra.authDomain,
dataBaseURL: Constants.manifest.extra.databaseURL,
projectId: Constants.manifest.extra.projectId,
storageBucket: Constants.manifest.extra.storageBucket,
messagingSenderId: Constants.manifest.extra.messagingSenderId,
appId: Constants.manifest.extra.appId,
};
const app = initializeApp(firebaseConfig);
export const firestore = {
instance: () => {
return getFirestore(app);
},
connectFirestoreEmulator: (host, port) => {
return connectFirestoreEmulator(getFirestore(app), host, port);
},
};
if (__DEV__) {
try {
firestore.connectFirestoreEmulator("localhost", "8080");
console.log("====================================");
console.log("connected to emulators....");
console.log("====================================");
} catch (error) {
console.log("====================================");
console.log(error, "error connectiong emulators");
console.log("====================================");
}
}
Since you mentioned that the error seems to happen only in Firestore, I have followed the documentation related to using the Firestore emulator, and my app successfully connects to the local emulator and retrieves local data.
I’m not sure if the way you export the Firestore instance is causing the issue, but the documentation shows that the function must be imported and used, passing the Firestore instance as an argument. This is the sample code I tested:
firestore-config.js
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
// Configuration keys
};
const app = initializeApp(firebaseConfig);
export const firestore = getFirestore(app);
app.js
import { firestore } from "./firestore-config";
import { getDoc, doc, connectFirestoreEmulator } from "firebase/firestore";
import "./App.css";
export default function App() {
try{
connectFirestoreEmulator(firestore, "localhost", "8080");
console.log("connected");
const docRef = doc(firestore, "localTest", "localTestDoc");
const getData = async () => {
const docSnap = await getDoc(docRef);
console.log(docSnap.data());
}
getData();
}
catch(err){
console.log("error: ", err)
}
return <div className="App"></div>;
}
I am able to see my data coming from the emulated Firestore as output. It would also be useful to see a full error stack trace, since the error from the title is not really that descriptive.
I am making a food delivery app using react-native and redux. I want to fetch the data from the firebase store and for that, I have written a function in the actions.js, but whenever I run the app it shows the Error
Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app).
Here is the function which I am using to fetch the data
action.js
import firebase from "firebase"
export const ProductDetails = (data) => {
return {
type: "PRODUCT_ITEMS",
payload: {
data,
},
};
};
var db = firebase.firestore();
var docRef = db.collection("Products").doc("Items");
export const FetchItems = () => {
return async function (dispatch) {
return await docRef
.get()
.then((doc) => {
if (doc.exists) {
console.log("Document Data", doc.data());
dispatch(ProductDetails(doc.data));
} else {
console.log("NO such document");
}
})
.catch((error) => {
console.log(error);
});
};
};
Here is my App.js file
import React, { useState } from "react";
import { StyleSheet, Text, View, Dimensions } from "react-native";
import { NavigationContainer } from "#react-navigation/native";
import AppStack from "./components/navigation/AppStack";
import firebase from "firebase";
import {Provider} from "redux"
import store from "./store"
import { useDispatch, useSelector, Provider } from "react-redux";
import store from "./redux/store";
import AppWrapper from "./AppWrapper";
export default function App() {
const firebaseConfig = {
};
if (firebase.apps.length === 0) {
firebase.initializeApp(firebaseConfig);
}
return (
<Provider store={store}>
<NavigationContainer>
<AppStack />
</NavigationContainer>
</Provider>
);;
}
I would recommend creating a separate file firebase.js and export Firebase services from there after initialization.
firebase.js
import firebase from 'firebase/app';
import 'firebase/firestore'
const firebaseConfig = {...};
if (!firebase.apps.length) {
firebase.initializeApp(config);
}
export const auth = firebase.auth();
export const firestore = firebase.firestore()
Then import these wherever you need them:
// App.js for example
import {firestore, auth} from './firebase.js'
//var docRef = firestore.collection("Products").doc("Items");
for users with expo(v44) and firebase(v9)
firebaseUtil.js
import { initializeApp, getApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";
// Initialize Firebase
const firebaseConfig = {
...
};
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
const auth = getAuth(app);
export { db, auth };
Login.js
import { auth } from "../../util/firebaseUtil";
export default function Login() {
const onSignUp = () => {
signInWithEmailAndPassword(auth, email, password);
};
return (
...
)
}
I think my error is caused by Webpack chunking(bootstrap). I did import the file with initializeApp(). My work around for who has the same problem.
Modularize the initializeApp in one file(initFire for me) and export anything(doesn't have to be app)
Import & Export before first usage of getApp()(methods like getAuth() will call it),
In this way, after Webpack it will still run first. (ES6 export {app} from "./initFire")
(This answer is grepped from my own GitHub Wiki, not plagiarizing)