Can't use firebase in React component, because it's not initialized [duplicate] - javascript

I am making a food delivery app using react-native and redux. I want to fetch the data from the firebase store and for that, I have written a function in the actions.js, but whenever I run the app it shows the Error
Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app).
Here is the function which I am using to fetch the data
action.js
import firebase from "firebase"
export const ProductDetails = (data) => {
return {
type: "PRODUCT_ITEMS",
payload: {
data,
},
};
};
var db = firebase.firestore();
var docRef = db.collection("Products").doc("Items");
export const FetchItems = () => {
return async function (dispatch) {
return await docRef
.get()
.then((doc) => {
if (doc.exists) {
console.log("Document Data", doc.data());
dispatch(ProductDetails(doc.data));
} else {
console.log("NO such document");
}
})
.catch((error) => {
console.log(error);
});
};
};
Here is my App.js file
import React, { useState } from "react";
import { StyleSheet, Text, View, Dimensions } from "react-native";
import { NavigationContainer } from "#react-navigation/native";
import AppStack from "./components/navigation/AppStack";
import firebase from "firebase";
import {Provider} from "redux"
import store from "./store"
import { useDispatch, useSelector, Provider } from "react-redux";
import store from "./redux/store";
import AppWrapper from "./AppWrapper";
export default function App() {
const firebaseConfig = {
};
if (firebase.apps.length === 0) {
firebase.initializeApp(firebaseConfig);
}
return (
<Provider store={store}>
<NavigationContainer>
<AppStack />
</NavigationContainer>
</Provider>
);;
}

I would recommend creating a separate file firebase.js and export Firebase services from there after initialization.
firebase.js
import firebase from 'firebase/app';
import 'firebase/firestore'
const firebaseConfig = {...};
if (!firebase.apps.length) {
firebase.initializeApp(config);
}
export const auth = firebase.auth();
export const firestore = firebase.firestore()
Then import these wherever you need them:
// App.js for example
import {firestore, auth} from './firebase.js'
//var docRef = firestore.collection("Products").doc("Items");

for users with expo(v44) and firebase(v9)
firebaseUtil.js
import { initializeApp, getApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";
// Initialize Firebase
const firebaseConfig = {
...
};
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
const auth = getAuth(app);
export { db, auth };
Login.js
import { auth } from "../../util/firebaseUtil";
export default function Login() {
const onSignUp = () => {
signInWithEmailAndPassword(auth, email, password);
};
return (
...
)
}

I think my error is caused by Webpack chunking(bootstrap). I did import the file with initializeApp(). My work around for who has the same problem.
Modularize the initializeApp in one file(initFire for me) and export anything(doesn't have to be app)
Import & Export before first usage of getApp()(methods like getAuth() will call it),
In this way, after Webpack it will still run first. (ES6 export {app} from "./initFire")
(This answer is grepped from my own GitHub Wiki, not plagiarizing)

Related

(React, and Firebase version 9.6.9) Firebase: Firebase App named '[DEFAULT]' already exists with different options or config (app/duplicate-app)

I am writing a React app with firebase version 9.6.9 for a login system, but this error keeps getting in my way. I have already tried this method:
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import { async } from '#firebase/util';
import { firebase } from "firebase/app";
import { getAuth, onAuthStateChanged, connectAuthEmulator,
signInWithEmailAndPassword, createUserWithEmailAndPassword,
signOut } from "firebase/auth";
export const firebaseApp = initializeApp({
//Configuration stuff
});
if (firebase.apps.length === 0/*or !firebase.apps.length*/) {
firebase.initializeApp(firebaseConfig);
}`
My current code looks like this:
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import { async } from '#firebase/util';
import { firebase } from "firebase/app";
import { getAuth, onAuthStateChanged, connectAuthEmulator,
signInWithEmailAndPassword, createUserWithEmailAndPassword,
signOut } from "firebase/auth";
export const firebaseApp = initializeApp({
//Configuration stuff
});
export const app = initializeApp(firebaseApp);
export const analytics = getAnalytics(app);
export const auth = getAuth(firebaseApp);
Any suggestions?
Why are you initializing your firebase app twice?
export const firebaseApp = initializeApp({
//Configuration stuff
});
export const app = initializeApp(firebaseApp); <- remove this line
you need to make sure that your firebase app is initialized only once, change your code to this:
export const firebaseApp = !getApps().length ? initializeApp(firebaseConfig) : getApp();
don't forget to import getApps() and getApp()
import { getApp, getApps, initializeApp } from 'firebase/app';
and by the way, you don't need to export const firebaseApp since you're not going to use it out of that file.
Look like this :
import firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
const firebaseConfig = {
apiKey: 'XXXXXXXXXXXXXX',
authDomain: 'XXXX.firebaseapp.com',
databaseURL: 'https://dburl.firebaseio.com',
projectId: 'proj-XXXX',
storageBucket: 'XXXXX.appspot.com',
messagingSenderId: 'XXXXXXX',
appId:XXXXXXXXXXXXXXXXXX"
};
firebase.initializeApp(firebaseConfig);
export const firebaseAuth = firebase.auth();
export const firestore = firebase.firestore()
then use :
import { firebaseAuth } from 'firebase'
const CustomComponent = props => {
const [email, setEmail] = useState()
const [password, setPassword] = useState()
const handleAuth = e => {
firebaseAuth.signInWithEmailAndPassword(email, password).then(res => {
console.log(res.user)
}).catch(err => {
const { code, message } = err
console.log(code, message)
})
}
return (<button onClick={handleAuth}>firebase</button>)

NextJs getServerSideProps cannot fetch data from Cloud Firestore Web version 9

I am using NextJs version 12.0.10 and firebase version 9.6.6 which use a modular system to import it.
When I run the function from my service to fetch data from firebase/firestore, it returns an error saying Cannot access 'getStories' before initialization. I'm confident all the logic & syntax are correct, as it works perfectly when I fetch it from inside the page render function.
Here is my getServerSideProps function:
pages/index.js
import '#uiw/react-markdown-preview/markdown.css';
import { useContext } from 'react';
import { getStories } from '../lib/services/StoryService';
import { truncate } from 'lodash';
import { convertSecondsToHumanReadableDiff } from '../lib/utils/common';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { AuthContext } from '../pages/_app';
import Navigation from '../components/Navigation';
export async function getServerSideProps() {
const fetchedStories = await getStories();
const stories = fetchedStories.docs.map((story) => {
return {
...story.data(),
id: story.id,
content: truncate(story.data().content, { length: 150, separator: '...' }),
};
});
return { props: { stories } };
}
const Blog = ({ stories }) => {
const router = useRouter();
const { user } = useContext(AuthContext);
return (
<div>
...
</div>
);
};
export default Blog;
lib/firebase/firebase.js
import { initializeApp } from 'firebase/app';
import { getAnalytics } from 'firebase/analytics';
import { getFirestore } from 'firebase/firestore';
import { getAuth } from 'firebase/auth';
const firebaseConfig = {
apiKey: 'XXX',
authDomain: 'XXX',
projectId: 'XXX',
storageBucket: 'X',
messagingSenderId: 'XXX',
appId: 'XXX',
measurementId: 'XXX',
};
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
export const database = getFirestore(app);
export const auth = getAuth(app);
lib/services/storyService.js
import {
collection,
query,
getDocs,
getDoc,
setDoc,
doc,
serverTimestamp,
orderBy,
} from 'firebase/firestore';
import { database } from '../firebase/firebase';
import slugify from 'slugify';
import { random } from 'lodash';
const storiesRef = collection(database, 'stories');
export const createStory = async (payload) => {
const slugTitle = slugify(payload.title);
const slug = slugTitle + '-' + random(0, 100000);
const updatedPayload = {
...payload,
slug,
type: 'published',
createdAt: serverTimestamp(),
};
return setDoc(doc(storiesRef, slug), updatedPayload);
};
export const getStories = async () => {
const q = query(storiesRef, orderBy('createdAt', 'desc'));
return getDocs(q);
};
export const getStoryBySlug = async (slug) => {
const docRef = doc(database, 'stories', slug);
return getDoc(docRef);
};
You are using getDocs, a client-side function of firebase, inside your getStories function, which is invoked in getServerSideProps, a node.js environment.
Instead you need to use the admin SDK for functions invoked in node.js environment (like getServerSideProps), e.g. like so:
import * as admin from "firebase-admin/firestore";
export const getStories = async () => {
return await admin
.getFirestore()
.collection(database, 'stories')
.orderBy('createdAt', 'desc')
.get()
};
export const getStoryBySlug = async (slug) => {
return await admin
.getFirestore()
.doc(database, 'stories', slug)
.get()
};
(sorry for the late answer, I still hope it helps OP or anyone else)

Firebase Reactjs - ae.collection is not a function

I can't figure out what is the error here. I made the tutorial Firebase/website and did the same things in my project. I am trying to print out the collection I created on Firebase in my React website but got the error at the line db.collection : Uncaught (in promise) TypeError: ae.collection is not a function
component.js :
// React
import { useState, useEffect } from "react";
import { db, collection, getDocs } from '../../../firebase.js';
const [holder, setHolder] = useState([]); // update
db.collection("holder").onSnapshot((snapshot) => {
setHolder(
snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
);
});
console.log({ holder });
update : firebase.js below
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import { getFirestore, collection, getDocs } from 'firebase/firestore/lite';
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
...
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
export const db = getFirestore(app);
Thank you !
You are using Firebase Modular SDK which has a completely new syntax and you must use the same in your code. Try refactoring the code to this:
// React
import { useState, useEffect } from "react";
import { db } from '../../../firebase.js';
import { onSnapshot, collection } from 'firebase/firestore'
const [holder, setHolder] = useState([]); // update
onSnapshot(collection(db, 'holder'), (snapshot) => {
setHolder(
snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
);
})
Also make sure your getFirestore import is from firebase/firestore and not from lite in firebase.js or you'll run into this issue:
import { getFirestore } from 'firebase/firestore';

Retrieving Firebase Data in a config.js file for React Native Expo App

I've been developing a React Native Expo App which is compatible with both iOS and Android devices. In this app I need to retrieve and render data from my google firebase database.
I would like to rewrite my firebase code into a config.js file as currently I have the firebase script inside each App screen which is causing issues. Instead, I want to write a config.js file which exports the data, allowing me to retrieve the data in each screen by the import statement:
import { CustomerData } from '../app/config.js';
The code below (minus the export statement) works just fine on each screen when I use the 'info' data retrieved. However this is causing issue when adding new features to screens and is an inefficient way to retrieve google firebase data.
I've attempted to write the config.js file like so:
import "firebase/firestore";
import * as firebase from "firebase";
import React, { useState, Component, useEffect } from "react";
import "react-native-gesture-handler";
const firebaseConfig = {
apiKey: <My Api Key>,
authDomain: <My AuthDomain>,
projectId: <My Project Id>,
storageBucket: <My storage Bucket>,
messagingSenderId: <Sender Id>,
appId: <App ID>,
measurementId: <Measurement ID>,
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
} else {
firebase.app();
}
function GetData() {
const [info, setInfo] = useState([]); // Initial empty array of info
useEffect(() => {
const dbh = firebase.firestore();
dbh
.collection("CustomerDatabase")
.get()
.then((querySnapshot) => {
const info = [];
querySnapshot.forEach((documentSnapshot) => {
info.push({
...documentSnapshot.data(),
key: documentSnapshot.id,
});
});
setInfo(info);
});
}, []);
export info;
I believe I need to add an export function which exports the retrieved data - 'info'. However I have attempted to place this export statement in different locations in the script and it returns the error
SyntaxError: 'import' and 'export' may only appear at the top level. (44:0)
Even when placing the export statement at the start of the script I still receive the same error. Also when removing the export state it throws the error:
TransformError SyntaxError: Unexpected token (44:15)
Indicating the last line as the culprit. This same code format works on the app screens however.
How would I export the 'info' data from within a config.js file? or do I have to stick to retrieving my firebase data from within each screens js file?
I ran this code, and except for the fact that you forgot to add a curly brace to close your GetData funtion, there appears to be no other error
import "firebase/firestore";
import * as firebase from "firebase";
import React, { useState, Component, useEffect } from "react";
import "react-native-gesture-handler";
const firebaseConfig = {
apiKey:"",
authDomain:"",
projectId:"",
storageBucket:"",
messagingSenderId:"",
appId:"",
measurementId:"",
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
} else {
firebase.app();
}
function GetData() {
const [info, setInfo] = useState([]); // Initial empty array of info
useEffect(() => {
const dbh = firebase.firestore();
dbh
.collection("CustomerDatabase")
.get()
.then((querySnapshot) => {
const info = [];
querySnapshot.forEach((documentSnapshot) => {
info.push({
...documentSnapshot.data(),
key: documentSnapshot.id,
});
});
setInfo(info);
});
}, []);
}
export {info};
It makes sense though because info is not a global variable, you declared info as a variable in GetData, so if you want it to be accessible you should return it in your GetData() function. Then you can now export GetData and you should get back info from the function.
import "firebase/firestore";
import * as firebase from "firebase";
import React, { useState, Component, useEffect } from "react";
import "react-native-gesture-handler";
const firebaseConfig = {
apiKey:"",
authDomain:"",
projectId:"",
storageBucket:"",
messagingSenderId:"",
appId:"",
measurementId:"",
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
} else {
firebase.app();
}
function GetData() {
const [info, setInfo] = useState([]); // Initial empty array of info
useEffect(() => {
const dbh = firebase.firestore();
dbh.collection("CustomerDatabase").get().then((querySnapshot) => {
const info = [];
querySnapshot.forEach((documentSnapshot) => {
info.push({
...documentSnapshot.data(),
key: documentSnapshot.id,
});
});
setInfo(info);
});
}, []);
return(info);
}
export {info};
//Then wherever you want to use info you can just do this...
import {GetData} from "filepath";
const info = GetData();
Another way I like to export state in my react apps is to define the state in my App.js so it's accessible to every component in my app. Example of how I would export a state holding the theme for my app below. I pass my state ad its setter as a prop to my AppRouting Component. And then whenever I have a component I want to have access to the theme in my AppRouting, I just do this: theme={props.theme} setTheme={props.setTheme}
import { useState } from "react";
import { Box, ThemeProvider, } from "#mui/material";
import { darkTheme } from "./Theming/AppTheme";
import AppRouting from "./Pages/AppRouting";
const App = () => {
const [theme, setTheme] = useState(darkTheme);
return(
<ThemeProvider theme={theme}>
<Box
sx={{
position:"absolute",
width:"100vw",
height:"auto",
minHeight:"100vh",
top:"0",
left:"0",
display:"flex",
backgroundColor:"background.default",
}}
>
<AppRouting
theme={theme}
setTheme={setTheme}
/>
</Box>
</ThemeProvider>
);
}
export default App;

Why firebase onAuthStateChanged always return a null value?

import firebase from "firebase/app";
import "firebase/auth";
import firebaseConfig from '../../FirebaseConfig';
import { useEffect, useState } from 'react';
if(!firebase.apps.length){
firebase.initializeApp(firebaseConfig);
}
const AuthChange = () => {
const [UserInfo, setUserInfo] = useState();
useEffect(() => {
firebase.auth().onAuthStateChanged(function(user) {
console.log('AuthChanged', user)
if (user) {
const information = {name: user.displayName}
setUserInfo(information);
} else {
setUserInfo(null);
}
});
}, [])
return UserInfo;
}
export default AuthChange;
The output is
Authentication.js:14 AuthChanged null
.
The output is always null, whether the user is signed in or not. How can I solve It?

Categories