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
Related
I use the Notistack library and forked it and then using VSCode to try to add a Redux store in the library that I want to expose to Apps.
I'm not so good with Typescript. I have some trouble hehe.
What I want to do is that when the app is using Notistack to show a snack message. I want to use Redux to update the message in real time, like a file up/download progress showing on the snack. It's here Notistack new Redux store(that i create here) come into play. I want Notistack to expose the Redux store to the app so the app can send redux dispatch into to Notistack Redux Store. and showing dispatched message in the Notistack SnackbarItem.tsx
(hope you understand)
When I compile in VSCode I get this error in my app:
Failed to compile.
./src/redux/root-reducer.js
Attempted import error: 'notistack' does not contain a default export (imported as 'NotisReducer').
My root-reducer in the App look like this:
import { combineReducers } from 'redux';
import NotisReducer from 'notistack';
import snackReducer from './snackbar/snack.reducer';
const rootReducer = combineReducers({
snack: snackReducer,
NotisReducer,
});
export default rootReducer;
As you see I import Notistack's NotisReducer and I think I have implemented that.
(I have used NPM link to add locally forked Notistack library into my app)
Now it looks like this here is Notistack's indext.js file where I expose Redux store as NotisReducer:
What I did in Notistack was I added a to index.d.ts:
I define the type store like this:
import * as React from 'react';
import { SnackbarClassKey } from '#material-ui/core/Snackbar';
import { ClickAwayListenerProps } from '#material-ui/core/ClickAwayListener';
import { TransitionProps } from '#material-ui/core/transitions/transition';
import { StandardProps } from '#material-ui/core';
import store from './Redux/store'; // MY STORE
...
...
export type store = store; // EXPORT IT
I'm not sure if this is correct as I could not set breakpoint in npm linked Notistack. Maybe it's to many problem now that must be fixed first.
In the file
SnackbarProvider.tsx
I did like this, importing the store type from index.d.ts):
import {
SnackbarProviderProps,
SnackbarKey,
SnackbarMessage,
OptionsObject,
RequiredBy,
ProviderContext,
TransitionHandlerProps,
store, // STORE
} from ".";
import createChainedFunction from "./utils/createChainedFunction";
export { store }; // EXPOSING IT
In the file
NotisReducer.js
I import the store to be sent to indext.js above
But as you saw above I get compiler error store is not exported.
Attempted import error: 'notistack' does not contain a default ex (imported as 'NotisReducer').
please advice :))
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?
I'm working on a React and Firebase project and I'm having trouble setting up the autocompletion on my code (I'm using VScode).
Here's what I've got so far:
HOW I'M PROVIDING FIREBASE TO MY APP COMPONENTS (VIA CONTEXT)
FirebaseContext.js
import React from 'react';
const FirebaseContext = React.createContext(null);
export default FirebaseContext;
firebase.js
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import 'firebase/functions';
// .env file in root folder
const config = {
apiKey: process.env.FIREBASE_APP_API_KEY,
authDomain: process.env.FIREBASE_APP_AUTH_DOMAIN,
databaseURL: process.env.FIREBASE_APP_DATABASE_URL,
projectId: process.env.FIREBASE_APP_PROJECT_ID,
storageBucket: process.env.FIREBASE_APP_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_APP_MESSAGING_SENDER_ID
};
firebase.initializeApp(config);
firebase.functions().useFunctionsEmulator('http://localhost:5000');
export default firebase;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import firebase from './helpers/firebase/firebase';
import FirebaseContext from './helpers/firebase/FirebaseContext';
import { BrowserRouter as Router} from "react-router-dom";
...
ReactDOM.render(
// HERE'S HOW I'M PROVIDING FIREBASE FOR MY APP
<FirebaseContext.Provider value={firebase}>
<Router>
<App/>
</Router>
</FirebaseContext.Provider>
,document.getElementById('root')
);
HOW I'M CONSUMING FIREBASE IN MY COMPONENTS
AddProductContainer.js
import React, { useEffect, useState, useCallback, useContext } from 'react';
import FirebaseContext from '../../../helpers/firebase/FirebaseContext';
function AddProductContainer() {
const firebase = useContext(FirebaseContext);
function saveToFirestore() {
// I DON'T HAVE ANY AUTOCOMPLETION FROM 'FIREBASE...'
firebase.firestore().collection('products').add({
title: productDetails.title.newTitle,
description: productDetails.description,
categories: productDetails.categories
});
}
}
QUESTION
How can I get autocompletion from Firebase inside a JavaScript project?
Note: All of my component files are .js. I'm not using Typescript.
Is there a way to use JSDoc annotations to get access to autocompletion in this case?
Something like:
/** #type {firebase} */
const firebase = useContext(FirebaseContext);
It would definitely be pretty tricky to do it the way you're doing it without Typescript or something, but can I suggest another option?
I don't think it's necessary to put the firebase object itself in context. Putting app in context might make sense (the object returned from firebase.initializeApp) if you were going to use more than one app or just wanted to be explicit, but it seems like firebase itself would make more sense being a direct import (import firebase from 'firebase/app') in any file that's using it. It won't create a second instance of firebase or anything if that's what you're concerned about, it's just a handle for the firebase library. It'll pick up the default app you initialized with firebase.initializeApp() as long as initializeApp() ran first. initializeApp() creates a global default firebase app that any invocation of Firebase methods will pick up.
If you're uncomfortable with globals, you can be explicit about the specific app you're working with by assigning const app = firebase.initializeApp(...), then passing app down through props or context, then always calling firebase packages with app as an argument, such as firebase.firestore(app).collection('products').etc... .
But there should be no cost to importing the firebase package directly at the top of any file you're using it in (and want autocomplete in).
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.
I created the configurations with firebase functions:config:set but when I try to access them I get an error:
import firebase from 'firebase';
import functions from 'firebase-functions';
import admin from 'firebase-admin';
admin.initializeApp(functions.config().firebase);
const config = {
apiKey: functions.config().todoservice.apikey,
....
};
const fire = firebase.initializeApp(config)
export { fire }
That's what the documentation recommends.
The todoservice that I am trying to access does exist.
But when I npm run build I get the following error
Module not found: Error: Can't resolve 'dns' in '/www/firebase-app/node_modules/isemail/lib'
Based on research I tried using few different versions of firebase-admin and firebase-functions but nothing seems to work.