Initialize Firebase references in two separate files in the new API - javascript

I have upgraded to the new API and don't know how to initialize Firebase references in two separate files:
/* CASE 1 */
// 1st file
var config = {/* ... */};
firebase.initializeApp(config);
var rootRef = firebase.database().ref();
// 2nd file - initialize again
var config = {/* ... */};
firebase.initializeApp(config);
var rootRef = firebase.database().ref();
RESULT: bundle.js:535 Uncaught Error: Firebase App named '[DEFAULT]' already exists.
/* CASE 2 */
// 1st file
var config = {/* ... */};
firebase.initializeApp(config);
var rootRef = firebase.database().ref();
// 2nd file - don't initialize
var rootRef = firebase.database().ref();
RESULT: bundle.js:529 Uncaught Error: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp().
Before the new API I just called
var myFirebaseRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
in each file, and it worked okay.

This is an issue I ran into as well upgrading to the new version of Firebase. You might want two separate firebase apps initialized, like explained in other answers, but I just wanted to use the refs in two different locations in my app and I was getting the same error.
What you need to do for this situation is to create a firebase module for your app that only initializes firebase once, then you import or require it elsewhere in your app.
This is pretty simple, here is mine: modules/firebase.js
import firebase from 'firebase';
var firebaseConfig = {
apiKey: "some-api-key",
authDomain: "some-app.firebaseapp.com",
databaseURL: "https://some-app.firebaseio.com",
storageBucket: "some-app.appspot.com",
};
var FbApp = firebase.initializeApp(firebaseConfig);
module.exports.FBApp = FbApp.database(); //this doesnt have to be database only
And then elsewhere in your application you simply:
import FBApp from '/your/module/location'
var messagesRef = FBApp.ref("messages/");

You need to name your different instances (Apps as Firebase calls them); by default you're working with the [DEFAULT] App, because that's the most common use case, but when you need to work with multiple Apps then you have to add a name when initialising:
// Intialize the "[DEFAULT]" App
var mainApp = firebase.intializeApp({ ... });
// Intialize a "Secondary" App
var secondaryApp = firebase.initializeApp({ ... }, "Secondary");
...
mainApp.database().ref("path/to/data").set(value);
secondaryApp.database().ref("path/to/data").set(anotherValue);
You can find a more example scenarios in the updated Initialize multiple apps section of the Add Firebase to your JavaScript Project guide.

If you don't have the control over where Firebase will be instantiated, you can do something like this:
try {
let firApp = firebase.app(applicationName);
return firApp;
} catch (error) {
return firebase.initializeApp({
credential: firebase.credential.cert(firebaseCredentials),
databaseURL: firebaseUrl
}, applicationName);
}
Firebase will try to get the application, if it doesn't exist, then you can initialize it freely.

I made the mistake by importing like this.
import firebase from 'firebase'
const firebaseConfig = {
apiKey: 'key',
authDomain: 'domain',
databaseURL: 'url',
storageBucket: ''
};
firebase.initializeApp(firebaseConfig);
This worked fine for a few days but when I tried to sign in with custom tokens my auth object was not changed. I had to refresh the page for it to update so I could make certain calls to the database which were protected by my own auth credentials rules.
".read": "$uid === auth.uid || auth.isAdmin === true || auth.isTeacher === true",
When I changed my imports to this it worked again.
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/database';
const firebaseConfig = {
apiKey: 'key',
authDomain: 'domain',
databaseURL: 'url',
storageBucket: ''
};
firebase.initializeApp(firebaseConfig);
Then whenever I need to use Firebase in a certain module I import this(notice the import from firebase/app instead of firebase):
import firebase from 'firebase/app';
And talk to certain services like so:
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// Authenticated.
} else {
// Logged out.
}
});
firebase.database().ref('myref').once('value').then((snapshot) => {
// do stuff with the snapshot
});

To make multiple instances using new firebase.initializeApp(), you need a second parameter for the firebase constructor:
firebase.initializeApp( {}, "second parameter" );
Compare it to the old way to generate multiple instances where
new Firebase.Context()
is the second parameter:
new Firebase('', new Firebase.Context() );

For a small fraction of the people here, this issue might be cause by trying to initialize fb admin on the same script that you used to initialize fb on the front end. If anybody is initializing firebase twice on the same script (once for admin and once for frontend), then you need initialize firebase admin in a different script than in front end, and do not import anything that is exported on the backend script on the frontend (and vise versa).

Related

Having error attempting to use RTDB in Expo managed

I'm attempting to use firebase realtime database on my app. I first authenticate and then I need to use the RTDB. Here is my attempt.
import { initializeApp } from 'firebase/app';
import 'firebase/auth';
import 'firebase/storage';
import { getDatabase } from "firebase/database";
import getEnvVars from '../environment';
const ENV = getEnvVars();
const firebaseConfig = {
apiKey: ENV.firebase.API_KEY,
authDomain: ENV.firebase.AUTH_DOMAIN,
databaseURL: ENV.firebase.DATABASE_URL,
projectId: ENV.firebase.PROJECT_ID,
storageBucket: ENV.firebase.STORAGE_BUCKET,
messagingSenderId: ENV.firebase.MESSAGING_SENDER_ID,
appId: ENV.firebase.APP_ID
};
initializeApp(firebaseConfig);
export const db = getDatabase();
The error I get is:
TypeError: (0, _database.getDatabase) is not a function. (In '(0, _database.getDatabase)()', '(0, _database.getDatabase)' is undefined)
You're mixing up the old, namespaced syntax of SDK versions 8 and lower, with the new, modular syntax of SDK versions 9 and above.
To get the database in v9, you call getDatabase() as a top-level function:
export const db = getDatabase();
I recommend keeping the Firebase documentation ready when going through this, as it has code samples for both the old and new syntax so you can easily compare. For this specific call, see the documentation on getting a database reference.

Vue + Firebase: Functions useEmulator() ignored

I found this line of code in the Firebase docs firebase.functions().useEmulator('localhost', 5001) that supposedly points your Vue app to the locally running emulator, but for some reason my project is ignoring said line of code and continues to call the remotely deployed function instead.
Here's what the relevant part of my #/plugins/firebase.js looks like:
import firebase from 'firebase/app';
import 'firebase/functions';
firebase.initializeApp({
apiKey: process.env.VUE_APP_FIREBASE_API_KEY,
authDomain: process.env.VUE_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.VUE_APP_FIREBASE_DATABASE_URL,
projectId: process.env.VUE_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.VUE_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.VUE_APP_FIREBASE_MESSAGE_SENDER_ID,
appId: process.env.VUE_APP_FIREBASE_APP_ID,
measurementId: process.env.VUE_APP_FIREBASE_MEASUREMENT_ID
});
firebase.functions().useEmulator('localhost', 5001);
const func = {
botcheck: firebase.app().functions('europe-west2').httpsCallable('validateRecaptcha'),
};
export { func };
And then to call the botcheck function, I'll run the following in a Vuex action:
const fb = require('#/plugins/firebase');
...
await fb.func.botcheck();
What am I doing wrong? How do I get it to correctly point to my locally running emulator?
Vue project versions:
vue: 2.6.11
firebase: 8.3.2
Functions project versions:
firebase-admin: 9.2.0
firebase-functions: 3.11.0
Let me know if I need to include additional information.
This line:
firebase.functions()
is functionally equivalent to:
firebase.app().functions('us-central1')
In your current code, you connect functions that don't specify a region to the emulator. Because you specify the region as europe-west2 when using it, you need to connect the europe-west2 functions to the emulator. You can do this by changing this line:
firebase.functions().useEmulator('localhost', 5001);
to use the correct region:
firebase.app().functions('europe-west2').useEmulator('localhost', 5001)
Additional Note: While firebase.functions() and firebase.app().functions() return the same instance of a Functions object (connected to the us-central1 region), firebase.app().functions('us-central1') (where you pass in the region) returns a different instance of Functions. You would need to connect each instance that you use to the emulator.
Here's your code as I make sure that useEmulator() is configured properly with Cloud Functions for Firebase Emulator. Feel free to try it:
import firebase from 'firebase/app';
import 'firebase/functions';
const firebaseConfig = {
// Your config
};
const app = firebase.initializeApp(firebaseConfig);
const functions = app.functions('europe-west2');
functions.useEmulator('localhost', 5001);
const func = {
botcheck: functions.httpsCallable('validateRecaptcha'),
};
export { func };

How to use firestore emulator with Nextjs

I'm trying to use Firebase Emulator on a local project based on Nextjs. Following the guidance from Firebase here I'm trying to use db.useEmulator('localhost', 8080); after I initialised Firebase but I have this error:
Error was not caught TypeError: db.useEmulator is not a function
at Module.eval (VM79706 firebase.js:30)
at eval (VM79706 firebase.js:91)
at Module../utils/firebase.js (_app.js?ts=1603918354205:23994)
...
I've been using the emulator to test cloud functions and it's working pretty well. I just don't understand how to connect it with Firestore.
Here is how I set up Firebase:
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import 'firebase/storage';
import 'firebase/analytics';
const clientCredentials = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL,
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
};
// Check that `window` is in scope for the analytics module!
if (typeof window !== 'undefined' && !firebase.apps.length) {
firebase.initializeApp(clientCredentials);
if ('measurementId' in clientCredentials) firebase.analytics();
const db = firebase.firestore();
if (process.env.NEXT_PUBLIC_DB_HOST === 'localhost') {
db.useEmulator('localhost', 8080);
}
}
export default firebase;
Any idea why I'm getting this error and how I connect Firebase emulator with Nextjs?
To answer my own question, the problem was that this method was introduced in the new version of firebase 8.0.0. I just had the update and voila!
Using firebase ver. 9.4.1.
You may using database UI for work with database locally. Url to database UI show, when start emulators.
Regular url: localhost:PORT/database

Vue-Firebase: How to connect to 2 firebases from the same app

I have two firebases on the same project and i need to connect to both of them.
There are two javascript files connecting to each firebase which seems ok.
I import both of them
import db from '../FireBase'
import mdb from '../MissionFireBase'
let MissionRef = mdb.ref('mission');
let TeamRef = db.ref('Teams');
let StartRef = db.ref('start');
db is an export of one firebase and mdb of another. On itself each one of them works but when i try to use both of them i get an error
index.cjs.js?3b8b:360 Uncaught FirebaseError {code: "app/duplicate-app", message: "Firebase: Firebase App named '[DEFAULT]' already exists (app/duplicate-app).", name: "[DEFAULT]", stack: "[DEFAULT]: Firebase: Firebase App named '[DEFAULT]…0)↵ at fn (http://localhost:8080/app.js:89:20)"}
To me it seems somewhere firebase gets a default id and when trying to use them both it conflicts. I tried calling each one from a different vue component but i get the same result.
The firebase connection is made like so
import Firebases from 'firebase'
let config = {
apiKey: "--",
authDomain: "--",
databaseURL: "--",
projectId: "--",
storageBucket: "--",
messagingSenderId: "--"
};
let apps= Firebases.initializeApp(config);
let mdb = apps.database();
export default mdb
Is this possible? Can i use two different firebase calls or would i need to merge them both together?
Thanks
That's definitely possible. You will need to create separate FirebaseApp instances for each, and then get your database from that.
var secondaryAppConfig = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
};
// Initialize another app with a different config
var secondary = firebase.initializeApp(secondaryAppConfig, "secondary");
// Retrieve the database.
var secondaryDatabase = secondary.database();
For more on this, have a look at the section using multiple projects in your application in the Firebase documentation.

React Native - Firebase credentials in separate file

My goal is to have my firebase setup in a firebase_setup.js file in my root directory of my React Native project. I want to do this because it will allow me to perform import firebaseApp from 'AppName/firebase_setup' in my login.js and signup.js files.
I don't want to keep copying and pasting my Firebase credentials in every component I want to use the firebaseApp variable in.
firebase_setup.js
import * as firebase from 'firebase';
// Initialize Firebase
const firebaseConfig = {
apiKey: "FIREBASE_API_KEY",
authDomain: "FIREBASE_AUTH_DOMAIN",
databaseURL: "FIREBASE_DB_URL",
storageBucket: "",
};
export default const firebaseApp = firebase.initializeApp(firebaseConfig);
However, when I refresh the iPhone simulator I get this error:
SyntaxError: AppName/firebase_setup.js: Unexpected token (11:15)
It seems to have some issue with me using export default on firebaseApp. Any insight on this issue would be greatly appreciated! Thanks!
Try changing the last line to:
const firebaseApp = firebase.initializeApp(firebaseConfig);
export default firebaseApp;
Why the syntax is invalid
Exporting a variable declaration list as "default" wouldn't make sense: for one, the list can have more than one element:
export default var a, b, c; // Non-sensical

Categories

Resources