Trouble adding authentication with React and Firebase - reactjs

I'm having issues adding authentication to an app I have been working on.
Everything works fine with firebase as-is without the auth, until I start adding these new lines, which are basically just:
export const provider = new firebase.auth.GoogleAuthProvider();
export const auth = firebase.auth();
import firebase, { auth, provider } from './firebase.js';
I have a file for my config (config.js), which just contains an export for DB_CONFIG (with all my correct info). Here's where I'm running into issues. The tutorial I'm following has firebase imported and initialized in the config file, while I am doing so in my App.js file. I've been trying different things for a couple hours and nothing is working for me. If I import firebase into my config and initializeApp there, it breaks my App.js. Here's a gist of my code vs. what I'm trying to follow.
Is there an easy way to get the auth and provider set up and imported into my App.js file without changing too much?

After looking at your code I made some changes to it, maybe this approach help?
import * as firebase from 'firebase'
import { DB_CONFIG } from './Config/config';
// Configure firebase and it will be available globally.
firebase.initializeApp(DB_CONFIG)
// Once initialized you just need to create the provider and auth
const provider = new firebase.auth.GoogleAuthProvider();
const auth = firebase.auth();
class App extends Component {
constructor(props){
super(props);
// And just call firebase.database() to access database functionality.
// You don't even need to assign it to a local variable as you can access
// it anywhere in your code just by importing firebase
// and calling firebase.database() and also firebase.auth()
this.databaseRef = firebase.database().ref().child('players');
}
}
PS: I would delete your gist because, even though you changed the config file, your configuration info is still available in the gist revisions...

Related

Importing firebase cloud functions in a React project

I am building a react app (this part might be inconsequential) and have a server cloud function built:
exports.myFunction = functions.https.onCall(async (data, context) => {
...
}
I know that calling this in my client would normally consist of calling
firebase.functions().httpsCallable('myFunction');
And I have tried this in a separate project, and it works. However, that was using a script tag to import the functions module in my index.html:
<script src="/__/firebase/7.7.9/firebase-functions.js"></script>
but in my current project, my modules are imported in my firebase.js source:
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
apiKey: ...
...
};
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
I wasn't able to find any example code for importing functions this way, and everything I have tried has failed.
How can I import functions so that I can invoke the above method? Even better, how could I figure this out on my own? (I have been relying on example code so far). I assume that these are referencing the NPM packages I have npm install'ed (or in my case, yarn add'ed), but I don't immediately see where the code is actually being referenced so I can work this out on my own.
As far what I have understood from you question it is regarding how can firebase cloud function module be imported while using a react app which is calling a HTTPS callable function at the client side.You can use any library or built-in command of your environment to call a HTTPS function.
I would recommend you to try the following to your imports and see if that works.
import { getFunctions, httpsCallable } from "firebase/functions";
OR
import * as functions from 'firebase-functions'; import React from 'react'; import { renderToString } from 'react-dom/server'; import App from './src/App';
Check the below for similar implementation examples to better understand this and implement according to your requirements.
How to call Firebase function from within react component
Call Firebase HTTPS callable function in react
Implement callable function in react app
Firebase callable function CORS

Firebase Error - ncaught FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created when not importing app

I noticed some weird behaviour in my react app, which I do not understand:
I created a firebase app object which I export:
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export default app;
When I dont import it in my other component, where I use getAuth etc., I still get the same error. When I import it in the "correct" component, everything works.
import app from "../firebase";
I don´t understand why, since the app object is not used in the component. Why do I need to import the object when I don´t even use it? I guess it is used... but I don´t understand how.

Is there a conflict between ReactJS Firebase and Firebase Functions?

I had a working ReactJS app that was using Firebase.
I am following Robin Wieruch's React/Redux/Firebase Tutorial.
I then added Firebase functions, and now my app fails to start. The error I get is, for example, app.database() is not a function when instantiating the Firebase Class.
Here is a brief snippet:
import app from 'firebase/app';
import 'firebase/auth';
import 'firebase/database';
import 'firebase/storage'
import config from './config'
class Firebase {
constructor() {
app.initializeApp(config);
/* Helper */
this.serverValue = app.database.ServerValue;
this.emailAuthProvider = app.auth.EmailAuthProvider;
/* Firebase APIs */
this.auth = app.auth();
this.db = app.database();
}
I have the app working in the old repository without functions, so the only thing I can figure is that adding Firebase functions has introduced some conflict.
The directory structure is:
src/
node_modules/
functions/
functions/node_modules/
Any thoughts?
Thanks!
Only a guess... Is it possible that you need to import functions, and this.functions = app.functions() as you have with db and auth?

How to initialize firebase in gatsby?

I'm stuck on making firebase work in my gatsby application that uses Redux with Redux-sagas. I know about the existence of firebase-sagas but I'm trying to make without using it.
I'm trying to init firebase auth by:
import * as firebase from 'firebase/app';
import 'firebase/auth';
export const app = firebase.initializeApp(
{
apiKey : "apiKey",
authDomain : "project.firebaseapp.com",
databaseURL : "https://project.firebaseio.com",
projectId : "project",
storageBucket : "project.appspot.com",
appId : "appId"
}
)
export const authRef = () => app.auth(); //also tried: firebase.auth() and firebase.auth(app)
//firebase.auth returns a function, but firebase.auth() throws error
I have the following config on my gatsby-node.js:
const path = require('path');
exports.onCreateWebpackConfig = ({ actions, plugins, loaders, getConfig }) => {
const config = getConfig()
config.resolve = {
...config.resolve,
mainFields: ['module', 'browser', 'main'],
alias: {
...config.resolve.alias,
['firebase/app'] : path.resolve(__dirname, 'node_modules/firebase/app/dist/index.cjs.js'),
['firebase/auth'] : path.resolve(__dirname, 'node_modules/firebase/auth/dist/index.cjs.js'),
}
}
actions.replaceWebpackConfig(config)
}
It trows the error:
{ [M [Error]: The XMLHttpRequest compatibility library was not found.]
code: 'auth/internal-error',
message: 'The XMLHttpRequest compatibility library was not found.' }
I think it's some problem related to webpack. I would love any insights on this problem :)
As Gatsby builds pages in a server environment, you can't access Firebase during Gatsby build time. Firebase calls (using the Web SDK) have to happen when the user is on a browser/client environment.
One solution to this problem is creating a function like so:
firebase.js:
import firebase from '#firebase/app';
import '#firebase/auth';
import '#firebase/firestore';
import '#firebase/functions';
const config = {
... firebase config here
};
let instance;
export default function getFirebase() {
if (typeof window !== 'undefined') {
if (instance) return instance;
instance = firebase.initializeApp(config);
return instance;
}
return null;
}
This file returns a function, which returns an instance of Firebase if the user has the global window available (e.g. on the browser). It also caches the Firebase instance to ensure it cannot be reinitialised again (in case of the user changing page on your website).
In your components, you can now do something similar to the following:
import getFirebase from './firebase';
function MyApp() {
const firebase = getFirebase();
}
As Gatsby will try to build this page into HTML during gatsby build, the firebase const will return null, which is correct, as the Firebase Web SDK cannot initialise on a server environment. However, to make use of Firebase on your website, you need to wait until Firebase is available (so the user has to have loaded your website), so we can make use of Reacts useEffect hook:
import React { useEffect } from 'react';
import getFirebase from './firebase';
function MyApp() {
const firebase = getFirebase();
useEffect(() => {
if (!firebase) return;
firebase.auth().onAuthStateChanged((user) => { ... });
}, [firebase]);
}
This works as Firebase is being used in a browser environment and has access to the browser, which is needed for the Web SDK to work.
It does have drawbacks; your compo have to return null in instances when you need Firebase to display content, which will mean your HTML build on the server will not contain any HTML, and it'll be injected via the client. In most cases though, such as an account page, this is fine.
If you need access to data from say Cloud Firestore to display page content, you're best using the Admin SDK to fetch content and add it to GraphQL during Gatsby build. That way it will be available on the server during build time.
Sorry if that was a waffle or not clear!

Implicitly initializing firebase in a React app

I'm attempting to combine implicit initialization for Firebase and a React app (created using CRA) as it seems like a good way to ensure I don't need to worry too much about configuring for different environments.
However, when running the app, if I make any attempt to use the firebase object I get the error Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app).
My index file has the Firebase files included before the app files and if I put a breakpoint in the Firebase-provided init then I can see that it is initializing the firebase object.
The App component is the one that comes with the CRA boilerplate:
mport React from 'react';
import firebase from 'firebase/app'
import 'firebase/functions'
import logo from './logo.svg';
import './App.css';
const App: React.FC = () => {
const helloWorld = firebase.functions().httpsCallable('helloWorld')
helloWorld().then(result => console.log({ result }))
return (
...
Any pointers?
I was doing it wrong. The init script was being called correctly and creating a global firebase object, which I was then overriding with my imports.
I removed the two imports in my component and changed the helloWorld declaration:
const helloWorld = window.firebase.functions().httpsCallable('helloWorld')
The typescript linter then complains that firebase doesn't exist on Window, so I've added a global.d.ts file containing this:
interface Window {
firebase: any
}
At some point, I'll work out the correct type for it, but it's got me past the problem.

Resources