I have a react/nextjs app and I have firebase.js as follow:
import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/analytics'
import 'firebase/firestore'
const firebaseConfig = {
apiKey: '...'
}
try {
firebase.initializeApp(firebaseConfig)
firebase.analytics()
} catch (err) {
if (!/already exists/.test(err.message)) {
console.error('Firebase initialization error', err.stack)
}
}
export default firebase
I kept getting
Firebase initialization error ReferenceError: navigator is not defined
after adding analytics to the firebase.js file. What is the correct way to add analytics to the app?
import { getAnalytics, isSupported } from "firebase/analytics";
const analytics = isSupported().then(yes => yes ? getAnalytics(app) : null);
Try this one
import firebase from "firebase/app"
import "firebase/auth"
import "firebase/firestore"
import "firebase/storage"
import "firebase/analytics"
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_API_KEY,
authDomain: process.env.NEXT_PUBLIC_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_PROJECT_ID,
appId: process.env.NEXT_PUBLIC_APP_ID,
storageBucket: process.env.NEXT_PUBLIC_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_MESSAGING_SENDER_ID,
measurementId: process.env.NEXT_PUBLIC_MEASUREMENT_ID,
}
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig)
}
// Auth export
export const auth = firebase.auth()
// Firestore exports
export const firestore = firebase.firestore()
export const serverTimestamp = firebase.firestore.FieldValue.serverTimestamp
export const fbTimestamp = firebase.firestore.Timestamp
export const fromMillis = firebase.firestore.Timestamp.fromMillis
export const increment = firebase.firestore.FieldValue.increment
// Storage exports
export const storage = firebase.storage()
export const analytics = () => {
if (typeof window !== "undefined") {
return firebase.analytics()
} else {
return null
}
}
export default firebase
ReferenceError: navigator is not defined
because there is no window object present during the server-side rendering of the Nextjs application.
Try:
if(typeof window != undefined){
firebase.analytics()
}
I just updated my firebase to version 9 and this error is not seen.
Update to version 9 could be a solution to this.
But for version 9, there are some changes in firebase declaration.
import firebase from 'firebase/compat/app'
import 'firebase/compat/auth'
import 'firebase/compat/firestore'
Using firebase V 9.16 this how I solved the issue
import { initializeApp } from "firebase/app";
import { getAnalytics, isSupported } from "firebase/analytics";
import { getFirestore } from "firebase/firestore"
const firebaseConfig = {
...
};
let app; let analytics; let db
if(typeof window != undefined){
app = initializeApp(firebaseConfig);
analytics = isSupported().then(yes => yes ? getAnalytics(app) : null);
db = getFirestore(app)
}
export {app, analytics, db}
In _app.js I import analytics and i use useEffect like
useEffect(() => {
analytics;
}, [])
Related
I have and Expo project with this firebase config file:
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
const firebaseConfig = {
...
};
if (!firebase.apps.length){
firebase.initializeApp(firebaseConfig);
}
export { firebase };
I'm calling its methods like this:
const [events, setEvents] = useState([]);
const evsRef = firebase.firestore().collection('testing');
const getEvents = () => {
evsRef.onSnapshot(
snapshot => {
const evs = [];
snapshot.forEach((doc)=>{
const {name, height, features:{good, better, best}} = doc.data();
evs.push({
key: doc.id,
name, height,
features:
{
good,
better,
best
}
})
})
setEvents(evs);
}
)
return;
}
useEffect(() => {
getEvents();
console.log('Testing: ', events);
},[events])
And I get this error:
TypeError: undefined is not an object (evaluating '_firebase.default.firestore')
Any ideas? I'm new to React-Native/Expo and I can't find any consisting examples as to what method to use for communication with firebase/firestore, so far I've been using collection(db, 'collection name') but this one seems more documented.
Turns out I was mixing up V9 with code from V8 as it was pointe out in the comments, the confusion started with me using the node.js examples as opposed to Web 9 examples, so be aware of that. Here's the code:
Firebase Config
import { initializeApp, getApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword } from "firebase/auth";
import geofire from 'geofire';
const firebaseConfig = {...};
const app = initializeApp(firebaseConfig);
const firestore = getFirestore(app);
export default firestore;
And this is the query code:
const getEvents = async (dbx) => {
const eventsCol = collection(dbx, 'testing');
const eventSnapshot = await getDocs(eventsCol);
const eventList = eventSnapshot.docs.map((doc) =>
({
...doc.data(),
key: doc.id
})
);
setEvents(eventList)
return eventList;
}
Google analytics for Firebase is on my Next.js app. I deployed my site to Vercel. I can't see visit log in the first visit to my site in my Firebase console. But refresh my site, the log is well recorded.
app.tsx
import type { AppProps } from "next/app"
import Head from "next/head"
import { useEffect } from "react"
import { analytics } from "../firebaseConfig"
function MyApp({ Component, pageProps }: AppProps) {
const a = analytics
return (
<div>This is an example</div>
)
}
export default MyApp
firebaseConfig.ts
// Import the functions you need from the SDKs you need
import { FirebaseApp, initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
// 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: 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_MEASURMENT_ID
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const initAnalytics = (args: FirebaseApp) => {
if (typeof window !== 'undefined') {
return getAnalytics(args)
} else {
return null
}
}
const analytics = initAnalytics(app)
export { app, analytics }
These sticks only updates when I visit my site AND refresh it.
I want to upload an image to firebase storage, version 9. I have working code for the firestore, but I cant for the life of me understand the firebase docs regarding uploading, and how to make it work for Vue (which also requires the import of a REF function).
my question is: How do I import the ref function in Vue and also import and use the ref function from firebase firestore?
This is what I have. It feels wrong to wrap the Firebase ref with a .value, but I just put it in there to get past the vue error.
vue component code fragment: <-- this works
if (imageFile.value) {
await uploadImage(imageFile.value);
console.log("image:" + url.value);
}
useStorage.js <--this is where everything breaks down trying to convert from Firebase 8 to 9. Is it the vue Ref function?
import { ref } from "vue";
import { projectStorage } from "../firebase/config";
import { uploadBytesResumable, getDownloadURL } from
"#firebase/storage";
const useStorage = () => {
const error = ref(null);
const url = ref(null);
const filePath = ref(null);
//I need to use ref with firestore here
const uploadImage = async (file) => {
filePath.value = `images/${file.name}`;
const storageRef = ref(projectStorage,
filePath.value).value;
try {
const res = await storageRef.put(file);
url.value = res.ref.getDownloadURL();
} catch (err) {
console.log(err.message);
error.value = err.message;
}
};
return { url, filePath, error, uploadImage };
};
export default useStorage;
config.js
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getStorage } from "firebase/storage";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
[info]
};
// init firebase
const firebaseApp = initializeApp(firebaseConfig);
// init firestore service
const db = getFirestore(firebaseApp);
// init firestore authorization
const auth = getAuth(firebaseApp);
const projectStorage = getStorage(firebaseApp);
export { db, projectStorage, auth };
You can set an alias for either of the imports as shown below:
import { ref } from "vue";
import { projectStorage } from "../firebase/config";
import { ref as storageRef } from "#firebase/storage";
const fileRef = storageRef(projectStorage, filePath.value);
// use storageRef here ^^^ instead of ref from vue
Also checkout: How to import two classes by the same name in javascript/es6?
I'm trying to setup firebase Auth into my nextjs project (it looks like the firebase documentation is not up-to-date via the release of the getAuth method).
While using firebaseUi (to get the automatic styling of the different auth providers), I get this error :
Here is the code (i'm just trying to render the firebaseUi component for now) :
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// Initialize Cloud Firestore
const db = getFirestore(app);
// Initialize Firebase Authentication
const auth = getAuth(app);
export { db, auth }
Then in a template page for signin :
import { NavBar } from '../components';
import { StyledFirebaseAuth } from 'react-firebaseui/StyledFirebaseAuth';
import { auth } from '../firebase/initFirebase';
import { GoogleAuthProvider } from 'firebase/auth';
const firebaseui = require('firebaseui')
// // Initialize the FirebaseUI Widget using Firebase.
var ui = new firebaseui.auth.GoogleAuthProvider(auth);
function Signup() {
const firebaseUiConfig = {
signInFlow: 'popup',
signInSuccessUrl: '/',
tosUrl: '/terms-of-service',
privacyPolicyUrl: '/privacy-policy',
signInOptions: [
GoogleAuthProvider.PROVIDER_ID
]
}
return (
<div>
<NavBar />
<StyledFirebaseAuth uiConfig={firebaseUiConfig} firebaseAuth={auth} />
</div>
)
}
export default Signup
Thanks a lot in advance for your help, I don't understand what's going on :(
// EDIT //
I understand it has to deal with SSR. So I did try to dynamically import firebaseUi with next/dynamic. I don't get the error any longer but the page is now blank (just the navbar component renders). Is it because I am passing props inappropriately ?
import dynamic from "next/dynamic";
import { NavBar } from '../components';
import { auth } from '../firebase/initFirebase';
import { GoogleAuthProvider } from 'firebase/auth';
const AuthComponent = dynamic(() =>
import('react-firebaseui/StyledFirebaseAuth').then((mod) => mod.StyledFirebaseAuth)
)
function Signup() {
const firebaseUiConfig = {
// signInFlow: 'popup',
signInSuccessUrl: '/',
tosUrl: '/legal',
privacyPolicyUrl: '/legal',
signInOptions: [
GoogleAuthProvider.PROVIDER_ID
]
}
return (
<div>
<NavBar />
<AuthComponent uiConfig={firebaseUiConfig} firebaseAuth={auth} />
</div>
)
}
export default Signup
The idea here to disable SSR on the page which used firebaseui.
This can be done in two steps.
Use firebase ui or any library which needs window keywork to work.
import React from 'react';
import Modal from '#leafygreen-ui/modal';
import * as firebaseui from 'firebaseui'
import 'firebaseui/dist/firebaseui.css'
export default function AuthUi({open, setOpen}) {
return (
<>
<Modal open={open} setOpen={setOpen}>
// Modal Content goes here.
// Signup widgets comes here
</Modal>
</>
);
}
while importing the library, do something like this.
//__app.js
// import AuthUi from '../components/authUi'; >> Replace this by code below
import dynamic from 'next/dynamic'
const AuthUi = dynamic(
() => import('../components/authUi'),
{ ssr: false }
);
Now you would be able to use firebaseui without window error.
I have it working with Firebase 8, but I can't seem to get Firebase 9 working...
Here is my firebaseConfig.js file:
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
const firebaseConfig = {
apiKey: 'AIzaSyCAAngD7340_noXs7eesCfE9Y3cwqmiZhU',
authDomain: 'svelte-todo-20f21.firebaseapp.com',
projectId: 'svelte-todo-20f21',
storageBucket: 'svelte-todo-20f21.appspot.com',
messagingSenderId: '402466412167',
appId: '1:402466412167:web:c739e7eb86fc5b6ac5ca22',
measurementId: 'G-2N348J0NTE'
};
const firebaseApp = initializeApp(firebaseConfig);
export const auth = getAuth(firebaseApp);
export const firestore = getFirestore(firebaseApp);
export default firebaseApp;
My auth.js file:
import { auth } from './firebaseConfig';
import { GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
// Sign in with popup && Google as the provider
const googleProvider = new GoogleAuthProvider();
export const googleSignIn = async () => {
await signInWithPopup(auth, googleProvider)
.then((user) => {
console.log(user);
})
.catch((error) => {
console.error(error);
});
};
And the index.svelte:
<script>
import { googleSignIn } from '../auth';
</script>
<button on:click={() => googleSignIn()}>Sign In</button>
Seems easy enough but I'm getting this error that I can't resolve...
"500
The requested module '/node_modules/.vite/firebase_firestore.js?v=42dbe183' does not provide an export named 'getFirestore'
SyntaxError: The requested module '/node_modules/.vite/firebase_firestore.js?v=42dbe183' does not provide an export named 'getFirestore'"
If it helps, someone suggested that I update my svelte.config.js file to the following...
/** #type {import('#sveltejs/kit').Config} */
const config = {
kit: {
// hydrate the <div id="svelte"> element in src/app.html
target: '#svelte',
vite: {
ssr: {
external: ['firebase']
}
}
}
};
export default config;