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
I am using NextJS and Firebase fairly new to both. My app is trying to collect data from firestore database on some occasions it works fine and sometimes it returns "n is undefined" refering to the firestore object "db". This happens when i call the "collection(db, "users", uid, "posts")" function in the [posts].js file. What is causing this?
Firebase.js
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import {getStorage} from "firebase/storage"
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "xxxxxxxxxxxxxxxxxxxxxxxxx",
projectId: "xxxxxxxxxxxxxxxxxxxx",
storageBucket: "xxxxxxxxxxxxxxxxxxxx",
messagingSenderId: "xxxxxxxxxxxxxxxx",
appId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const storage = getStorage(app);
export const db = getFirestore(app);
[posts].js
import { useRouter } from 'next/router'
import { useState, useEffect } from 'react';
import Link from 'next/link';
import { useAuth } from '../context/AuthContext'
import styles from '../styles/dashboard.module.css';
import Image from 'next/image';
import { collection, getDocs } from "firebase/firestore";
import { db } from '../lib/firebase';
export default function Posts(){
const [queriedData, setQueriedData] = useState([]);
const router = useRouter()
const { uid } = router.query
useEffect(() => {
async function fetchData() {
const postsRef = collection(db, "users", uid, "posts");
const snapshot = await getDocs(postsRef);
const postData = snapshot.docs.map((doc) => {
const data = doc.data();
data.id = doc.id;
return data;
});
setQueriedData(postData);
}
fetchData();
}, []);
return(
{queriedData.map((post) =>(<div>post.title</div>)
)}
}
Added await to the collection function and I also thought it was internet issues hence i setup a firebase emulator still got the same behavior.
I tried console logging "db" right after the line "export const db = getFirestore(app);". I got out "[Object Object]"
I've been getting this error working on react-native. Firebase connects normally, with auth(), but I can't seem to get it working for firestore. The problem only occurred on Android Emulator, the iOS one is working fine.
error only occurred on Android Virtual Device, the iOS one work perfectly
Here is Firebase file (removed some information about the app)
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
// 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 = {
apiKey: '',
authDomain: '',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: '',
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth();
const db = getFirestore(app);
export { auth, db };
Here is where I used Firestore function
import React, { useState } from 'react';
import { useTailwind } from 'tailwind-rn/dist';
import useAuth from '../../hooks/useAuth';
import { doc, serverTimestamp, setDoc } from 'firebase/firestore';
import { db } from '../../Firebase';
import { useNavigation } from '#react-navigation/native';
const ModalScreen = () => {
const tw = useTailwind();
const [image, setImage] = useState('');
const [job, setJob] = useState('');
const [age, setAge] = useState('');
const navigation = useNavigation();
const inCompleteForm = !image || !job || !age;
const updateUserProfile = () => {
setDoc(doc(db, 'users', user.uid), {
id: user.uid,
displayName: user.displayName,
photoURL: image,
job,
age,
timestamp: serverTimestamp(),
})
.then(() => {
navigation.navigate('Home');
})
.catch(err => {
alert(err.message);
});
};
import {
View,
Text,
SafeAreaView,
TouchableOpacity,
Image,
StyleSheet,
Platform,
} from 'react-native';
import React, { useRef, useState, useLayoutEffect } from 'react';
import { useTailwind } from 'tailwind-rn/dist';
import { useNavigation } from '#react-navigation/native';
import useAuth from '../../hooks/useAuth';
import Icon from 'react-native-vector-icons/Ionicons';
import Swiper from 'react-native-deck-swiper';
import { doc, onSnapshot } from 'firebase/firestore';
import { db } from '../../Firebase';
const HomeScreen = () => {
const navigation = useNavigation();
const tw = useTailwind();
const [profiles, setProfiles] = useState([]);
const { user, logOut } = useAuth();
const swipeRef = useRef(null);
useLayoutEffect(() => {
onSnapshot(doc(db, 'users', user.uid), snapshot => {
if (!snapshot.exists) navigation.navigate('Modal');
});
}, []);
Error
[2022-03-15T06:49:42.961Z] #firebase/firestore: Firestore (9.6.8): Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds.
This typically indicates that your device does not have a healthy Internet connection at the moment. The client will operate in offline mode until it is able to successfully connect to the backend.
WARN [2022-03-15T06:53:06.868Z] #firebase/firestore: Firestore (9.6.8): Connection WebChannel transport errored: {"defaultPrevented": false,
i got the same problem, try to see here or the code i will give bellow if it can solve the problem :)
import { initializeFirestore } from 'firebase/firestore'
const database = initializeFirestore(app, {
experimentalAutoDetectLongPolling: true
})
const "database" in my example is not the same as "db" in your code, keep the both
Props.navigation was an empty object no matter what I tried...
so Im trying to render a screen change conditionally in app.js
I've tried about a hundred different things and cant figure it out, its been days. please help!
There is no error it just doesnt navigate away once a user is signed in. in firebase... it shows they are signed in...
I think i need a subscribe function ... like below but I need help making it work as I am jon snow and this somehow needs to mix with useeffect.
function handleStateChange () {
let previousValue = isLoggedIn
isLoggedIn = store.getState().logIn.isSignedIn;
if(previousValue !== isLoggedIn){
console.log(`${previousValue} ${isLoggedIn}`)
}
}
store.subscribe(handleStateChange);
here is the console.log...
undefined false
undefined false
false true
false true
APP.JS....
import { StyleSheet, Text, View,Button } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import WorkoutNavigator from './navigation/WorkoutNavigator';
import Colors from './constants/Colors';
import { createStore , combineReducers, applyMiddleware} from 'redux';
import workOutReducer from './store/Reducers';
import {Provider, useSelector } from 'react-redux';
import ReduxThunk from 'redux-thunk'
import { useEffect, useState } from 'react';
import { initializeApp } from "firebase/app";
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
import LoginScreen from './screens/LoginScreen';
import loginReducer from './store/AuthStore/reducer';
const rootReducer = combineReducers({
favorites: workOutReducer,
logIn: loginReducer
});
const store = createStore(rootReducer, applyMiddleware(ReduxThunk));
export default function App(props) {
const [loggedIn, setLoggedIn] = useState(false);
let isLoggedIn = store.getState().logIn.isSignedIn;
useEffect(()=> {
const firebaseConfig = {
},[]);
useEffect(()=>{
setLoggedIn(isLoggedIn)
}, [isLoggedIn])
return (
<Provider store={store}>
{loggedIn ? <WorkoutNavigator /> : <LoginScreen /> }
</Provider>
);
}
...here is my reducer...
import { SIGNIN, SignInACtion } from "./actions"
const initialState = {
isSignedIn: false,
}
const loginReducer = (state = initialState, action) => {
switch(action.type){
case SIGNIN:
return{
isSignedIn: true
}
default: return state;
}
};
export default loginReducer;
here is the action in case you need to see it...
import axios from "axios";
import firebase from "firebase/compat/app";
import "firebase/compat/auth";
export const SIGNUP = 'SIGNUP';
export const SIGNIN = 'SIGNIN';
export const SignUpAction = (phone) => {
return async dispatch => {
try{
await axios.post('https://us-central1-one-time-password-d8d7a.cloudfunctions.net/createUser',{
phone
})
await axios.post('https://us-central1-one-time-password-d8d7a.cloudfunctions.net/requestOneTimePass',{
phone
})
}catch(error){console.log(error)};
dispatch({type: SIGNUP, phone: phone})
};
};
export const SignInACtion = (phone, code) => {
return async dispatch => {
try{
let {data}= await axios.post('https://us-central1-one-time-password-d8d7a.cloudfunctions.net/verifyPassword',{
phone,
code
});
firebase.auth().signInWithCustomToken(data.token)
} catch (error){console.log(error)};
dispatch({type: SIGNIN, payload: {
isSignedin: true,
}})
}
}
Firebase'auth provides a simple way to check whether the user authenticated, let's leverage this feature and refactor code as below:
import { StyleSheet, Text, View, Button } from "react-native";
import { LinearGradient } from "expo-linear-gradient";
import WorkoutNavigator from "./navigation/WorkoutNavigator";
import Colors from "./constants/Colors";
import { createStore, combineReducers, applyMiddleware } from "redux";
import workOutReducer from "./store/Reducers";
import { Provider, useSelector } from "react-redux";
import ReduxThunk from "redux-thunk";
import { useEffect, useState } from "react";
import { initializeApp } from "firebase/app";
import firebase from "firebase/compat/app";
import "firebase/compat/auth";
import "firebase/compat/firestore";
import LoginScreen from "./screens/LoginScreen";
import loginReducer from "./store/AuthStore/reducer";
const rootReducer = combineReducers({
favorites: workOutReducer,
logIn: loginReducer,
});
const store = createStore(rootReducer, applyMiddleware(ReduxThunk));
export default function App(props) {
const [loggedIn, setLoggedIn] = useState(null);
const authenticateUser = () => {
// Detected if user is already logged in
firebase.auth().onAuthStateChanged((user) => {
if (user) {
setLoggedIn(true);
} else {
setLoggedIn(false);
}
});
};
let isLoggedIn = store.getState().logIn.isSignedIn;
useEffect(() => {
if (!loggedIn) {
authenticateUser();
}
}, [loggedIn]);
if (loggedIn === null) return null;
return (
<Provider store={store}>
{loggedIn ? <WorkoutNavigator /> : <LoginScreen />}
</Provider>
);
}
Not sure why I am getting this error, here's my setup. this error only happens for firestore. Auth, functions, storage, realtimedb work not sure what I'm missing. I followed The firebase documentation to set up.
firebase.js
import { initializeApp } from "firebase/app";
import { initializeAppCheck, ReCaptchaV3Provider } from "firebase/app-check";
import { getDatabase, connectDatabaseEmulator } from "firebase/database";
import {
getAuth,
connectAuthEmulator,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
} from "firebase/auth";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
import {
getFunctions,
connectFunctionsEmulator,
httpsCallable,
} from "firebase/functions";
import { getStorage, connectStorageEmulator } from "firebase/storage";
import Constants from "expo-constants";
// Initialize Firebase
const firebaseConfig = {
apiKey: Constants.manifest.extra.apiKey,
authDomain: Constants.manifest.extra.authDomain,
dataBaseURL: Constants.manifest.extra.databaseURL,
projectId: Constants.manifest.extra.projectId,
storageBucket: Constants.manifest.extra.storageBucket,
messagingSenderId: Constants.manifest.extra.messagingSenderId,
appId: Constants.manifest.extra.appId,
};
const app = initializeApp(firebaseConfig);
export const firestore = {
instance: () => {
return getFirestore(app);
},
connectFirestoreEmulator: (host, port) => {
return connectFirestoreEmulator(getFirestore(app), host, port);
},
};
if (__DEV__) {
try {
firestore.connectFirestoreEmulator("localhost", "8080");
console.log("====================================");
console.log("connected to emulators....");
console.log("====================================");
} catch (error) {
console.log("====================================");
console.log(error, "error connectiong emulators");
console.log("====================================");
}
}
Since you mentioned that the error seems to happen only in Firestore, I have followed the documentation related to using the Firestore emulator, and my app successfully connects to the local emulator and retrieves local data.
I’m not sure if the way you export the Firestore instance is causing the issue, but the documentation shows that the function must be imported and used, passing the Firestore instance as an argument. This is the sample code I tested:
firestore-config.js
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
// Configuration keys
};
const app = initializeApp(firebaseConfig);
export const firestore = getFirestore(app);
app.js
import { firestore } from "./firestore-config";
import { getDoc, doc, connectFirestoreEmulator } from "firebase/firestore";
import "./App.css";
export default function App() {
try{
connectFirestoreEmulator(firestore, "localhost", "8080");
console.log("connected");
const docRef = doc(firestore, "localTest", "localTestDoc");
const getData = async () => {
const docSnap = await getDoc(docRef);
console.log(docSnap.data());
}
getData();
}
catch(err){
console.log("error: ", err)
}
return <div className="App"></div>;
}
I am able to see my data coming from the emulated Firestore as output. It would also be useful to see a full error stack trace, since the error from the title is not really that descriptive.
I'm building a react app, and I want to integrate google signin using firebase. I've followed the firebase documentation in implementing it, yet I keep getting this error - "TypeError: firebase.auth.GoogleAuthProvider is not a constructor".
Here's my code;
firebase.prod.js
import Firebase from "firebase/app";
import "firebase/firestore";
import "firebase/auth";
import "firebase/storage";
const config = {
apiKey: "AIzaSyASOat6CaIWxzwnepoGBHDpltnf9jH1QH0",
authDomain: "cv-builder-c0429.firebaseapp.com",
databaseURL: "https://cv-builder-c0429.firebaseio.com",
storageBucket: "cv-builder-c0429.appspot.com",
};
const firebase = Firebase.initializeApp(config);
export { firebase };
signin.js
import React, { useState, useContext } from "react";
import { FirebaseContext } from "../context/firebase";
export default function SignUp() {
const { firebase } = useContext(FirebaseContext);
const googleSignIn = () => {
var provider = new firebase.auth.GoogleAuthProvider();
provider.addScope('profile');
provider.addScope('email');
firebase.auth()
.signInWithPopup(provider)
.then((result) => {
console.log(result)
}).catch((error) => {
console.log(error);
});
};
return (
<button onClick={googleSignIn}>Sign in with google</button>
)
};
Any help in fixing this will be appreciated.