React Native Project
Firebase had been setup in the App entrypoint for a long time using:
import firebase from 'firebase';
firebase.initializeApp({
apiKey: '...',
authDomain: '...',
databaseURL: '...',
projectId: '...',
storageBucket: '...',
messagingSenderId: '...',
});
and had been working properly for Firebase Database
but upon upgrading to 4.6.0 and adding trying to use within my components, I get the following error:
Unhandled JS Exception: Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app).
import firebase from 'firebase';
import 'firebase/firestore';
const db = firebase.firestore();
Hmmm this issue does not seem to follow the issue template. Make sure you provide all the required information.
Seems like this will turn out to be a timing issue, and that firebase.firestore() is likely getting invoked before your firebase.initializeApp() code. But there's not enough code here to tell, since the relationship of those two code snips is unclear.
Thanks @katowulf . It seems it's actually a timing issue like you suggested. I was calling:
const db = firebase.firestore() in a Component's constructor so I didn't expect it to get fired on App load, since that Component is not rendered yet. But I noticed I don't get the error if I make the call in a function elsewhere.
If anyone else stumbles upon this, you can do a simple interval check to await the initial app construction.
let firebaseAppDefined = false
setInterval(() => {
if (!firebaseAppDefined) {
if (firebase.app()) {
// Your code here
firebaseAppDefined = true
}
}
}, 100)
In my case I had to wait until the app was ready before being able to initialize FirebaseUI (auth widget).
@corysimmons thanks for the workaround, Cory. I wish there is an event which alarms when a firebase app initialized so we don't have to set intervals.
Same. I wish more companies ate their own dog food in combination with whatever the most likely tech their product will be used with (React) then provided tons of resources and special treatment for those things.
Just to chime in here, when you are attempting to use firebase without passing a Firebase app around, load order matters.
An example:
You have two files: foo.js and bar.js
foo.js
import firebase from 'firebase/app';
firebase.initializeApp({ ... });
bar.js
import firebase from 'firebase/app';
import 'firebase/firestore';
const db = firebase.firestore();
In this scenario, loading bar.js before foo.js will fail 100% of the time. In reality bar.js has a dependency on the app created in foo.js and you should either:
import foo.js before bar.js in all cases where you need bar.js
OR (and much easier to reason about)
Add a dependency to foo.js in bar.js as you need the app created there.
An easier way to do this would be to actually pass around the FirebaseApp created by calling initializeApp(). That would look something like this:
foo.js
import firebase from 'firebase/app';
export const app = firebase.initializeApp({ ... });
bar.js
import { app } from 'foo.js';
import firebase from 'firebase/app';
import 'firebase/firestore';
const db = firebase.firestore(app);
Now you are much more explicit about your dependencies and the code will always load in the correct order.
@corysimmons actually there is a callback dude:
const config = {};
firebase.initializeApp(config);
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in and currentUser will no longer return null.
} else {
// No user is signed in.
}
});
Most helpful comment
Just to chime in here, when you are attempting to use firebase without passing a Firebase
apparound, load order matters.An example:
You have two files:
foo.jsandbar.jsfoo.jsbar.jsIn this scenario, loading
bar.jsbeforefoo.jswill fail 100% of the time. In realitybar.jshas a dependency on the app created infoo.jsand you should either:import
foo.jsbeforebar.jsin all cases where you needbar.jsOR (and much easier to reason about)
Add a dependency to
foo.jsinbar.jsas you need the app created there.An easier way to do this would be to actually pass around the
FirebaseAppcreated by callinginitializeApp(). That would look something like this:foo.jsbar.jsNow you are much more explicit about your dependencies and the code will always load in the correct order.