Firebase intellisense / autocompletion on JavaScript React project in VSCode - reactjs

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).

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

Typescript npm library can't export Redux store please advice

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 :))

How do I fix a Firebase 9.0 import error? "Attempted import error: 'firebase/app' does not contain a default export (imported as 'firebase')."

I am trying to implement firebase in my React application but it seems my version of importing is outdated.
Here is my code:
import firebase from "firebase/app";
import "firebase/auth";
const app = firebase.initializeApp({
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_FIREBASE_APP_ID,
});
export const auth = app.auth();
export default app;
I've replaced my config keys with process.env.REACT_APP_FIREBASE... as they are stored in another local .env file. I've also tried different ways of importing firebase, but it seems most posts are outdated. This is the error I am getting:
./src/firebase.js
Attempted import error: 'firebase/app' does not contain a default export (imported as 'firebase').
I also have another file for authContext so I will need to keep the 'auth' keyword in my firebase.js file:
import React, { useContext, useState, useEffect } from "react";
import { auth } from "../firebase";
const AuthContext = React.createContext();
export function useAuth() {
return useContext(AuthContext);
}
const AuthProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState();
function signup(email, password) {
return auth.createUserWithEmailAndPassword(email, password);
}
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
setCurrentUser(user);
});
return unsubscribe;
}, []);
const value = {
currentUser,
signup,
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};
export default AuthProvider;
With version 9 things changed a bit for importing firebase, but there is no need to downgrade to a previous version, there is a "compatibility" option so can use the /compat folder in your imports, like this
import firebase from 'firebase/compat/app';
From the Firebase upgrade guide:
In order to keep your code functioning after updating your dependency
from v8 to v9 beta, change your import statements to use the "compat"
version of each import. For example:
// v9 compat packages are API compatible with v8 code
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
Follow the instructions in the documentation, which specifically calls out the steps for version 9:
Install Firebase using npm:
npm install firebase
Initialize Firebase in your app and create a Firebase App object:
import { initializeApp } from 'firebase/app';
// TODO: Replace the following with your app's Firebase project
configuration const firebaseConfig = { //... };
const app = initializeApp(firebaseConfig);
This is completely different than any method for any previous version of the Firebase SDKs. Note that you are importing individual functions from the Firebase SDK, not objects or namespaces.
To work with Firebase Auth, again follow the instructions in the documentation for v9:
import { getAuth, createUserWithEmailAndPassword } from "firebase/auth";
const auth = getAuth();
createUserWithEmailAndPassword(auth, email, password);
Again note that you're importing functions to call directly, not objects with methods.
Compare to the old process with version 8: Upgrade to Firebase JS 8.0.0: Attempted import error: 'app' is not exported from 'firebase/app' (imported as 'firebase')
The error comes when you are using Firebase greater than V8.
There is an easy fix for this though, firebase includes backward compatibility. All you need to do is change your import from firebase/app to firebase/compat/app.
This will change:
import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/auth';
to:
import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import 'firebase/compat/auth';
Check your firebase version using the following command on npm
$ firebase -V
If your firebase version is v8 import as following
import firebase from "firebase/app"
import "firebase/auth"
If your firebase version is v9 import as following
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
You should downgrade your firebase version to 8.9.1 if you are using version 9.0
and then import firebase like this:
import firebase from "firebase/app"
Firebase v9 comes with new API designed to facilitate tree-shaking (removal of unused code). This will make your app as small and fast as possible.
The /compat packages are created for compatibility and to make the upgrade to the modular API easier. With the downside of not getting the performance perks. To get the performance benefits of the modular design, use getApps instead:
import { getApps, initializeApp } from 'firebase/app';
if (!getApps().length) {
initializeApp({
// your config
});
}
From the library's JSDoc: getApps return A (read-only) array of all initialized apps..
There is also a getApp function that When called with no arguments, the default app is returned. When an app name is provided, the app corresponding to that name is returned. An exception is thrown if the app being retrieved has not yet been initialized.
Uninstall and reinstall firebase to a downgraded version. I just did this, installed version 8.10.0, and works fine.
you need to do this if you are doing this on October 21 and greater days
import {initializeApp} from 'firebase/app'
import 'firebase/firestore'
import 'firebase/auth'
import 'firebase/storage'
var config = {
apiKey: "xxxxx",
authDomain: "xx.firebaseapp.com",
projectId: "cxxx7",
storageBucket: "cxxx",
messagingSenderId: "xx",
appId: "zzze",
measurementId: "xxx"
}
const firebaseApp = initializeApp(config);
export default firebaseApp;

What does "import the individual SDK components you intend to use" in firebase?

I'm trying to create a signup page using react with firebase for the backend and this is the error in the console.
When deploying Firebase apps to production, it is advisable to only import
the individual SDK components you intend to use.
For the module builds, these are available in the following manner
(replace <PACKAGE> with the name of a component - i.e. auth, database, etc):
CommonJS Modules:
const firebase = require('firebase/app');
require('firebase/<PACKAGE>');
ES Modules:
import firebase from 'firebase/app';
import 'firebase/<PACKAGE>';
Typescript:
import firebase from 'firebase/app';
import 'firebase/<PACKAGE>';```
To simplify it, when you use require("firebase"); or import firebase from "firebase";, you import EVERYTHING. More often than not you don't use every library listed below.
For testing, importing from the root package "firebase" is fine, but when you deploy to production/compile your app, you shouldn't use it - which is what this error is saying.
Remember: Import what you need and don't import what you don't.
import firebase from "firebase";
is effectively the same as
import firebase from "firebase/app"; // Analytics
import "firebase/analytics"; // Analytics
import "firebase/auth" // Authentication
import "firebase/firestore" // Cloud Firestore
import "firebase/functions" // Cloud Functions for Firebase Client SDK
import "firebase/messaging" // Cloud Messaging
import "firebase/storage" // Cloud Storage
import "firebase/performance" // Performance Monitoring
import "firebase/database" // Realtime Database
import "firebase/remoteConfig" // Remote Config
In most cases for React, you want to import from the React Native Firebase (RNFB) packages like "#react-native-firebase/app", "#react-native-firebase/database" and so on.
To get access to the underlying firebase library for the RNFB libs, you would use:
import firebase from "#react-native-firebase/app";
// or
import database, { firebase } from "#react-native-firebase/database";

Is it possible to wrap next-auth Provider within redux Provider?

If I'm already using next-auth within my next.js app can I add redux around it inside _app.js somehow?
what i tried is this:
import React from "react"
import { Provider } from 'next-auth/client'
import {Provider as ReduxProvider} from 'react-redux';
import {configureStore} from './store/configureStore';
import '../public/styles.css'
const store = configureStore();
export default function App ({ Component, pageProps }) {
return (
<ReduxProvider store={store}>
<Provider
// next-auth params, etc.
is this correct? does it work this way?
i'll also need to use redux-saga, new to the whole thing so i'm at a setup stage yet
The answer is YES. You can do that. I've tried myself and it works perfectly.

Resources