Using Firebase with React in Firebase Hosting - reactjs

I'm developing a React app created with "create react app" (https://github.com/facebookincubator/create-react-app).
It will be hosted in Firebase Hosting and I'll like to use implicit initialization as describe in documentation (https://firebase.google.com/docs/web/setup#sdk_imports_and_implicit_initialization), to deploy to multiple projects (I have a dev project and several production projects)
<script src="/__/firebase/init.js"></script>
I need to get the "firebase" object initialized in the script above in my React components. How should I import it in multiple React components files?
I'm aware that this will be only available when I serve it with "firebase serve" during development and when I deploy it, so during development I'm trying to add
<script src="https://www.gstatic.com/firebasejs/4.1.1/firebase.js"></script>
<script>
// Initialize Firebase
// TODO: Replace with your project's customized code snippet
var config = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
messagingSenderId: "<SENDER_ID>",
};
firebase.initializeApp(config);
</script>
code to my index.html file as describe in Firebase docs. However, when I try to import Firebase in ReactComponent it doesn't find it or complains about not initialize project (what I'm doing in the html tag)
How do I import Firebase initialized App and Firebase libraries from my html script tags??

As you are using create-react app and thus webpack, you should already be using nodejs firebase:
npm install --save firebase
To get the config on the fly when deployed, you have to access this url:
/__/firebase/init.json
So you need to make an async call to get the json object stored on this location, before you try to initiliaze firebase. So here is some sample code (using axios for the async call) to include in your index.js:
import React from "react";
import ReactDOM from "react-dom";
import * as firebase from "firebase/app";
import axios from "axios";
const getFirebaseConfig = new Promise((resolve, reject) => {
axios
.get(`/__/firebase/init.json`)
.then(res => {
resolve(res.data);
})
.catch(err => reject(err));
});
getFirebaseConfig
.then(result => {
firebase.initializeApp(result);
ReactDOM.render(
<div>XXXXX</div>,
document.getElementById("root")
);
})
.catch(err => console.log(err));
Also in order to make this more streamlined (use dev firebase config with npm start, and get prod firebase configurations on the fly if deployed) you can do something like the below:
fbconfig.js:
if (process.env.NODE_ENV === "production") {
module.exports = require("./prod");
} else {
module.exports = require("./dev");
}
dev.js:
const firebaseConfig = {
// your dev firebase configuration
apiKey: "xxxxx",
authDomain: "xxxxx",
databaseURL: "xxxxxx",
projectId: "xxxxxx",
storageBucket: "xxxxx",
messagingSenderId: "xxxxx"
};
const getFirebaseConfig = new Promise((resolve, reject) => {
resolve(firebaseConfig);
});
export default getFirebaseConfig;
prod.js:
import axios from "axios";
const getFirebaseConfig = new Promise((resolve, reject) => {
axios
.get(`/__/firebase/init.json`)
.then(res => {
resolve(res.data);
})
.catch(err => reject(err));
});
export default getFirebaseConfig;
And finally in index.js:
import getFirebaseConfig from "./fbconfig";
getFirebaseConfig.then(result => {
firebase.initializeApp(result);
...etc
)}
.catch(err => console.log(err));

You're providing the firebase API directly in the browser with a script tag. It's already going to be available in the browser when you run your bundle.
You're using webpack behind the scenes with create-react-app, but I think you might need to eject it so you can tell it that this package is going to be available on your environment (browser) using the externals property.
https://webpack.js.org/configuration/externals/
From what I understand from this issue, it's not possible to add externals to webpack using create-react-app.
https://github.com/facebook/create-react-app/issues/780
Maybe it's best to drop the <script> tag with the firebase and just install and import it directly on your CRA project.
This might help:
https://www.codementor.io/yurio/all-you-need-is-react-firebase-4v7g9p4kf

Just try to install firebase package via npm. Then you can easily use it wherever you want in any react component by importing with
import firebase from 'firebase';
You can also import firebase in some configureFirebase.js file where you can initialize firebase app with some configs, then export configured firebase instance and use this instance in any component
Its would be helpful:
import firebase from 'firebase'
const config = { /* COPY THE ACTUAL CONFIG FROM FIREBASE CONSOLE */
apiKey: "unreadablestuff",
authDomain: "your-domain-name.firebaseapp.com",
databaseURL: "https://your-domain-name.firebaseio.com",
storageBucket: "your-domain-name.appspot.com",
messagingSenderId: "123123123123"
};
const fire = firebase.initializeApp(config);
export default fire;

Related

NextJS/Firebase - implementing firebase analytics throw error: Missing App configuration value

i am using Next JS 13 with default pages directory and i use database for my project. Everything works fine, until i started to implementing firebase analytics.
First it throwed that window is undefiend. I solved it by checking window. After that it worked so i wanted to test logEvent() function in my index.js page.
And it throw FirebaseError: Installations: Missing App configuration value: "projectId" (installations/missing-app-config-values).
I tried to use proccess.env.NEXT_PUBLIC but it didnt worked.
import { initializeApp} from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
import { getStorage } from 'firebase/storage';
import { getAnalytics } from 'firebase/analytics';
const firebaseConfig = {
apiKey: process.env.API_KEY,
authDomain: process.env.AUTH_DOMAIN,
projectId: process.env.PROJECT_ID,
storageBucket: process.env.STORAGE_BUCKET,
messagingSenderId: process.env.MESSAGING_SENDER_ID,
appId: process.env.APP_ID,
measurementId: process.env.MEASUREMENT_ID,
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
export const storage = getStorage(app);
export const analytics = typeof window !== 'undefined' ? getAnalytics(app) : null;
export default app;
Index.js example
<Button
key={`${name}_${index}`}
href={url}
mouseEnter={() => selectedImg !== img && handleMouseEnter(img)}
customStyles={'py-5 bg-primary-blue/60'}
onClick={() => (analytics ? logEvent(analytics, name) : {})}
> Test </Button>
Have someone similiar problem and solved it?
As the error says, the 'appId' is missing in your config object. You could try to copy it again in the Firebase Console to make sure you're using the updated one.
SOLVED: There was problem that i was using .env file, but in next js env variables should be inside next.config so it will load during build time.

Creating a Gradle build file for React App

I am trying to set up a starter React project. I have used a create-react-app to create a starter app. I linked it to our Firebase account, and made a simple page to display stored dummy data.
We initialized the firebase within our project using firebase init then installed the following dependencies: firebase cloud functions, firebase firestore.
Here is our App.js
import './App.css';
import React from 'react';
import { initializeApp } from 'firebase/app';
import { getFirestore } from "firebase/firestore";
import { collection, query, where, getDocs, initializeFirestore } from "firebase/firestore";
import { useState } from "react";
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "hidden",
authDomain: "hidden",
projectId: "hidden",
storageBucket: "hidden",
messagingSenderId: "hidden",
appId: "hidden"
};
// Initialize Firebase
const firebaseapp = initializeApp(firebaseConfig);
const db = getFirestore(firebaseapp);
function App() {
const [firebaseData, updateData] = useState([]);
//getPreferences(updateData);
return (
<div className="App">
<header className="App-header">
<div>{firebaseData.map(item => <div> {item} </div>)}</div>
<button onClick={() => getPreferences(updateData)}>Fetch Data</button>
</header>
</div>
);
}
async function getPreferences(updateData) {
const q = query(collection(db, "preferences"));
const querySnapshot = await getDocs(q);
let data = [];
querySnapshot.forEach((doc) => {
data.push(JSON.stringify(doc.data()));
});
updateData(data);
}
export default App;
We are running the following commands to run the app locally: npm install, npm install firebase, and npm start.
We are trying to create a single Grade build file to package everything which would run all of these commands and allow to launch the app.
We used the following command to initialize Gradle: gradle init --type basic --dsl groovy --project-name
Here is what I have for Gradle build file:
plugins {
id "com.moowork.node" version "1.2.0"
id 'com.google.gms.google-services'
}
apply plugin: 'base'
apply plugin: "com.moowork.node"
apply plugin: 'com.google.gms.google-services'
node {
version = "16.2.0"
download = true
}
dependencies {
classpath 'com.google.gms:google-services:4.3.10'
implementation platform('com.google.firebase:firebase-bom:29.3.1')
implementation 'com.google.firebase:firebase-auth'
implementation 'com.google.firebase:firebase-firestore'
implementation 'com.google.firebase:firebase-functions'
}
task bundle(type: NpmTask, dependsOn: npmInstall) {
args = ['run', 'build']
}
assemble.dependsOn(bundle)
And I'm getting the following error when trying to run gradle:
Where:
Build file '/Users/rkudryashov/Desktop/PartnerUp/build.gradle' line: 10
What went wrong:
Plugin [id: 'com.google.gms.google-services'] was not found in any of the following
sources:
Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
Plugin Repositories (plugin dependency must include a version number for this
source)
I am trying to make it so all of the dependencies are installed locally when running gradle even if a person doesn't have those installed.
Where did we go wrong?

Firebase and reactjs: Firebase App named '[DEFAULT]' already exists (app/duplicate-app) [duplicate]

I started a project and occurred an error when importing firebase in more than one component.
In this firebase start file:
import firebase from 'firebase'
const firebaseConfig = {
apiKey: "fdsfsdfdsf",
authDomain: "fdsfdsfsdfdsf",
databaseURL: "sdfdsfdsf",
projectId: "dsfdsfdsf",
storageBucket: "dsfdsfdsf",
messagingSenderId: "dsfdsfsdfdsf"
}
const FbApp = firebase.initializeApp(firebaseConfig)
export default FbApp.auth()
Then in the components:
import firebase from '../lib/firebaseClient'
With a single component works well, but if I add a new component with:
import firebase from '../lib/firebaseClient'
The application fail:
FirebaseError: Firebase: Firebase App named '[DEFAULT]' already exists (app/duplicate-app).
I had same issue, then I found out this:
if (!firebase.apps.length) {
firebase.initializeApp({});
}
https://github.com/zeit/next.js/issues/1999
The solution:
import firebase from 'firebase'
try {
firebase.initializeApp({
databaseURL: 'dfgdfg'
})
} catch (err) {
// we skip the "already exists" message which is
// not an actual error when we're hot-reloading
if (!/already exists/.test(err.message)) {
console.error('Firebase initialization error', err.stack)
}
}
const auth = firebase.auth()
export default auth
My understanding is that the error is due to calling initializeApp() more than once for your database. Scan through your code to make sure you only call initializeApp() once. For me, this included checking any js files that might be calling the method and checking for duplicate js files in your html file.
I recently solved this error in my own code. My issue was caused by accidentally linking my javascript file, which calls initializeApp(), in the head and in the body of my html file. My fix was to delete the duplicate javascript tag in the head of my html file so only one existed in the body.
On serverside something like this should work
const admin = require('firebase-admin');
const serviceAccount = require('./../../credentials/server');
// Check if firebase already been initialized
if (!admin.apps.length) {
// Initialize Firestore.
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
}
Summarizing all good answers.
A better fix would be to load environment variables from .env.local into process.env.
//.env.local
NEXT_PUBLIC_FIREBASE_API_KEY=
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
NEXT_PUBLIC_FIREBASE_APP_ID=
Next up, we can initialize the Firebase SDK on the client-side like this.
//shared/configs/firebase.js
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
const clientCredentials = {
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,
};
if (!firebase.apps.length) {
firebase.initializeApp(clientCredentials);
}
export default firebase;
Finally, import the Firebase deps to other file.
//pages/index.js
import firebase from '../shared/configs/firebase';
So I ran into this issue because of some aspect of Next's hot reloading. I was using code like the following to ensure that I didn't call initializeApp more than once:
export let adminClient;
adminClient = adminClient || admin.initializeApp({...});
This didn't work because it seemed like the hot reloading was clearing adminClient, so I kept trying to call initializeApp, even though firebase still had the app recorded as being initialized.
To fix this, I used the following snippet:
const getAppInstance = () => {
if (admin.apps.length) {
return admin.apps[0];
} else {
return initApp();
}
}
export const adminClient = getAppInstance();
which works on a fresh server start, or when hot reloading due to code changes in development.
If you are using a new Modular SDK v9.0.1 then it might not support the "firebase" namespace.
The Implementation, I used
import { initializeApp, getApps } from "firebase/app"
import { getFirestore } from "firebase/firestore"
import { getAuth } from "firebase/auth"
//App configure
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_MESSAGGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_MEASUREMENT_ID
};
if (!getApps().length) {
console.log(`...`)
}
const app = initializeApp(firebaseConfig)
const db = getFirestore(app)
const auth = getAuth(app)
export {db, auth}
export default app
Reference:
StackOverflow: Visit
Firebase Docs: Visit
Firebase Tutorial Setup: Visit

React NextJS Firebase error refresh Firebase App named '[DEFAULT]' already exists

I started a project and occurred an error when importing firebase in more than one component.
In this firebase start file:
import firebase from 'firebase'
const firebaseConfig = {
apiKey: "fdsfsdfdsf",
authDomain: "fdsfdsfsdfdsf",
databaseURL: "sdfdsfdsf",
projectId: "dsfdsfdsf",
storageBucket: "dsfdsfdsf",
messagingSenderId: "dsfdsfsdfdsf"
}
const FbApp = firebase.initializeApp(firebaseConfig)
export default FbApp.auth()
Then in the components:
import firebase from '../lib/firebaseClient'
With a single component works well, but if I add a new component with:
import firebase from '../lib/firebaseClient'
The application fail:
FirebaseError: Firebase: Firebase App named '[DEFAULT]' already exists (app/duplicate-app).
I had same issue, then I found out this:
if (!firebase.apps.length) {
firebase.initializeApp({});
}
https://github.com/zeit/next.js/issues/1999
The solution:
import firebase from 'firebase'
try {
firebase.initializeApp({
databaseURL: 'dfgdfg'
})
} catch (err) {
// we skip the "already exists" message which is
// not an actual error when we're hot-reloading
if (!/already exists/.test(err.message)) {
console.error('Firebase initialization error', err.stack)
}
}
const auth = firebase.auth()
export default auth
My understanding is that the error is due to calling initializeApp() more than once for your database. Scan through your code to make sure you only call initializeApp() once. For me, this included checking any js files that might be calling the method and checking for duplicate js files in your html file.
I recently solved this error in my own code. My issue was caused by accidentally linking my javascript file, which calls initializeApp(), in the head and in the body of my html file. My fix was to delete the duplicate javascript tag in the head of my html file so only one existed in the body.
On serverside something like this should work
const admin = require('firebase-admin');
const serviceAccount = require('./../../credentials/server');
// Check if firebase already been initialized
if (!admin.apps.length) {
// Initialize Firestore.
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
}
Summarizing all good answers.
A better fix would be to load environment variables from .env.local into process.env.
//.env.local
NEXT_PUBLIC_FIREBASE_API_KEY=
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
NEXT_PUBLIC_FIREBASE_APP_ID=
Next up, we can initialize the Firebase SDK on the client-side like this.
//shared/configs/firebase.js
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
const clientCredentials = {
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,
};
if (!firebase.apps.length) {
firebase.initializeApp(clientCredentials);
}
export default firebase;
Finally, import the Firebase deps to other file.
//pages/index.js
import firebase from '../shared/configs/firebase';
So I ran into this issue because of some aspect of Next's hot reloading. I was using code like the following to ensure that I didn't call initializeApp more than once:
export let adminClient;
adminClient = adminClient || admin.initializeApp({...});
This didn't work because it seemed like the hot reloading was clearing adminClient, so I kept trying to call initializeApp, even though firebase still had the app recorded as being initialized.
To fix this, I used the following snippet:
const getAppInstance = () => {
if (admin.apps.length) {
return admin.apps[0];
} else {
return initApp();
}
}
export const adminClient = getAppInstance();
which works on a fresh server start, or when hot reloading due to code changes in development.
If you are using a new Modular SDK v9.0.1 then it might not support the "firebase" namespace.
The Implementation, I used
import { initializeApp, getApps } from "firebase/app"
import { getFirestore } from "firebase/firestore"
import { getAuth } from "firebase/auth"
//App configure
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_MESSAGGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_MEASUREMENT_ID
};
if (!getApps().length) {
console.log(`...`)
}
const app = initializeApp(firebaseConfig)
const db = getFirestore(app)
const auth = getAuth(app)
export {db, auth}
export default app
Reference:
StackOverflow: Visit
Firebase Docs: Visit
Firebase Tutorial Setup: Visit

How to access an already initialized firebase app in React-native?

This maybe a very novice question but I am stuck at here. I am a begineer in React-native and currently working with firebase real-time db with react. I've already initialized my firebase app in one screen(login.js). Since I am using firebase 3.X I cannot reinitialize that app again in another screen. How can I access that already initialized app into another screen(register.js)?
And for the modular Firebase Web SDK 9 and up:
import { initializeApp } from "firebase/app";
import Constants from "expo-constants";
// Initialize Firebase
const firebaseConfig = {
apiKey: Constants.manifest.extra.apiKey,
authDomain: Constants.manifest.extra.authDomain,
projectId: Constants.manifest.extra.projectId,
storageBucket: Constants.manifest.extra.storageBucket,
messagingSenderId: Constants.manifest.extra.messagingSenderId,
appId: Constants.manifest.extra.appId,
measurementId: Constants.manifest.extra.measurementId,
};
const app = initializeApp(firebaseConfig);
export default app;
And then where you need it:
import app from '../config/firebaseConfig';
This is using Expo and 'expo-contants' (https://docs.expo.dev/versions/latest/sdk/constants/) to avoid committing your keys to your Github repo. If not using Expo then you can use react-native-dotenv (https://www.npmjs.com/package/react-native-dotenv) which does the same for pure react native apps.
Here is how you export Firebase Config
Make sure you have added firebase to your project by npm install firebase --save
then create a config file at ./Config/FirebaseConfig.js
Add the below code in your file.
import Fb from 'firebase';
const config = {
apiKey: 'apiKey',
authDomain: 'projectId.firebaseapp.com',
databaseURL: 'https://databaseName.firebaseio.com',
};
const Firebase = Fb.initializeApp(config);
export default Firebase;
After this you can import firebase in any of your component by import Firebase from 'Firebase';

Resources