Is Firebase Firestore working in React Native Expo? - firebase

I found out some documentation in official expo forum about firestore and everything seems to be working. And I were able to implement whole login, sign up flow with various providers from firebase. But I can not run any query from firestore. I am doing it like this:
const[dataSource, setDataSource] = React.useState({});
const getMealTypes = (mealTypes) =>{
const Meals = [];
mealTypes.get().then(function (doc) {
if (doc.exists) {
const {title, count} = doc.data();
Meals.push({
key: doc.id,
title,
count
})
} else {
console.log("No such document!");
}
}).catch(function (error) {
console.log("Error getting document:", error);
});
console.log(Meals);
setDataSource(Meals);
}
React.useEffect(() => {
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
const mealTypes = firebase.firestore().collection('mealTypes');
getMealTypes(mealTypes);
setDataSource([]);
}, []);
I have tried many more ways to get that response, but it never go into promise after get() function. Is get() broken in expo or am I doing something wrong?
Any help would be appreciated!

what version of firebase? there was a regression in support for react-native in the javascript sdk for firebase recently and the team is working on resolving that, until then i would recommend using version 7.9.0, which you will get if you run expo install firebase with the latest version of expo installed in your project

Related

connecting to firestore emulator with #firebase/testing

I am trying to test a firebase app locally.
I am running the test with firebase emulators:exec --only firestore 'mocha -r ts-node/register src/**/*.spec.ts
In my spec, I import #firebase/testing and setup my app and followed the directions from
https://firebase.google.com/docs/rules/unit-tests
I have a FirebaseService which is a singleton wrapper for my methods into which I inject my firebase app.
In production, I'll inject the firebase, and it gets initialized in the FirebaseService in testing, I initialize outside of the service.
The wrapper is fairly simple
export const FirebaseService = (function(): FirebaseSrvc {
let firebase;
const fbServiceObj: FirebaseSrvc = {
getInstance: (firebaseConfig, firebaseCore, initialize) => {
firebase = firebaseCore;
if (initialize && firebase.apps.length === 0) {
firebase.initializeApp(firebaseConfig);
}
return fbServiceObj;
},
createActivity: async (title: string) => {
try {
const firebaseUid = firebase.auth().currentuser.uid;
const newActivity: ActivityProps = {
title,
created_at: 123445,
created_by: firebaseUid,
public: false,
available_to: [firebaseUid],
};
console.log(' before create', newActivity);
const createResponse = await firebase
.firestore()
.collection('activities')
.doc(stringToSafeId(title))
.set(newActivity);
console.log('create response', createResponse);
return true;
} catch (e) {
console.log('error creating activity', e);
}
},
getActivity: async (title: string): Promise<ActivityProps> => {
try {
const actResponse: DocumentReferenceTo<ActivityProps> = await firebase
.firestore()
.collection('activities')
.doc(stringToSafeId(title))
.get();
return actResponse as ActivityProps;
} catch (e) {
console.log('error getting activity from firebase', e);
}
},
};
return fbServiceObj;
})();
The test I am attempting to run is
import * as firebase from '#firebase/testing';
import { assert } from 'chai';
import 'mocha';
import * as appConfig from '../../app-dev.json';
import { FirebaseService } from '../services/FirebaseService';
firebase.initializeTestApp({ ...appConfig.expo.extra.firebase, auth: { uid: 'random', email: 'test#test.com' } });
describe('Activity', async () => {
const fb = FirebaseService.getInstance(appConfig.expo.extra.firebase, testApp, false);
const activityData = new Activity(fb);
beforeEach(async () => await firebase.clearFirestoreData({ projectId }));
it('should create a new activity', async () => {
await activityData.set('test-activity'); // this runs FirebaseService.createActivity
const findActivity = await activityData.get('test-activity'); // this run FirebaseService.getActivity
assert(findActivity.title === 'test-activity');
});
});
When I run the test I get an error
Your API key is invalid, please check you have copied it correctly.] {
code: 'auth/invalid-api-key',
message: 'Your API key is invalid, please check you have copied it correctly.'
}
I can confirm that the API key which is passed into firebase.initializeTestApp matches the Web API Key in my firebase console.
I have also downloaded the google-services.json from my firebase console and lists
{
"api_key": [
{ "current_key": different_from_web_key}
]
}
And I have replaced my existing key with this new key, I still get the same error.
I have also tried setting up initializeTestApp({ projectId }) which is how the example from firebase docs sets it up, and I receive the same result.
I am using the same project details to run a project locally in android studio, and I am able to authenticate and write to firestore, so the API key I am using does work, but it appears to have issues being used in the test app.
This usually doesn't have a specific way to solve it. It might be that even a new copy and paste of the API key to the parameters, might make it work and the error to disappear.
I would recommend you to take a look at the following posts from the Community, that have some possible fixes for the error that you are facing.
Firebase Error: auth/invalid-api-key, Your API key is invalid, please check you have copied it correctly
Invalid API Key supplied using Firebase
In addition to that, since Firebase has free support offers, I think you reaching out to the Firebase support would help you fix this quickly. You should be able to contact directly for free.
Let me know if the information helped you!

This operation is not supported in the environment this application is runnung on [duplicate]

I develop a react-native (expo) mobile app and try to sign in with a google account to firebase, but I get an error:
"auth/operation-not-supported-in-this-enviroment. This operation is not supported in the enviroment this application is running on. "location.protocol" must be http, https or chrome-extension and web storage must be enabled"
Code:
loginGoogle() {
var provider = new firebase.auth.GoogleAuthProvider();
provider.addScope('profile');
provider.addScope('email');
firebase.auth().signInWithPopup(provider).then(function(result) {
var token = result.credential.accessToken;
var user = result.user;
return true;
}).catch(function(error) {
alert(error.code + '\n' +
error.message + '\n' +
error.email + '\n' +
error.credential);
return false;
});
}
signInWithPopup is not supported in react-native. You will need to use a third party OAuth library to get the OAuth ID token or access token and then sign in with Firebase:
const cred = firebase.auth.GoogleAuthProvider.credential(googleIdToken, googleAccessToken);
firebase.auth().signInWithCredential(cred)
.then((result) => {
// User signed in.
})
.catch((error) => {
// Error occurred.
});
Firebase does not support signInWithPopup in a React Native environment.
You can view a full list of supported environments on this page.
You can also submit a feature request for extended Firebase support for React Native here.
If you are using expo bare workflow or simple React native cli (or in simple words which contain android and ios folder) then simply use "React Native Firebase" library.
Here is the link https://rnfirebase.io/
But if you are using expo managed workflow(which donot contain android and ios folder ) then you have to follow below steps .
1.setup google developer account
use this guide to setup : https://docs.expo.dev/versions/latest/sdk/google/
Note that: use host.exp.exponent as the package name.
Another problem you may face in this step is generation of hash,which I also faced,the reason for that error is java dev kit(JDK) is not install ,so do install it before proceeding to this step.
2.Setup Firebase account
Simply setup firebase project as you set before, enable google sign in service
but this time the only change is you have to add client ID of your google developer account in (safest client id field) which will popup once you click on edit Google signin in firebase
look like this
3.Coding Part
import * as Google from 'expo-google-app-auth'; //imported from expo package
import {
GoogleAuthProvider,getAuth
} from 'firebase/auth';
import { initializeApp } from "firebase/app";
import { firebaseconfig } from '[your firebase credentials]';
const app=intitializeApp(firebaseconfig)
const auth=getAuth(app);
async function signInWithGoogleAsync() {
try {
const result = await Google.logInAsync({
androidClientId: 'cliend id from google dev console',
iosClientId: 'client id from google dev console for ios app(if you setup)',
scopes: ['profile', 'email'],
});
if (result.type === 'success') {
console.log(result)
const credential = GoogleAuthProvider.credential(result.idToken, result.accessToken);
// Sign in with credential from the Facebook user.
signInWithCredential(auth, credential)
.then(async result => {
console.log(result)
})
.catch(error => { console.log(error) });
return result.accessToken;
} else {
console.log("cancelled by user")
return { cancelled: true };
}
} catch (e) {
console.log(e);
return { error: true };
}//
}

Firebase sdk with react native unable to see anything

I am following this tutorial on RN with Firestore. I've so far only used the Firebase Web SDK installed via
npm install firebase -save
With the following example code:
constructor(props) {
super(props);
this.ref = firebase.firestore().collection('sessions');
this.unsubscribe = null;
this.state = {
dataSource: [],
loading: true,
};
}
componentDidMount() {
this.unsubscribe = this.ref.onSnapshot(this.onCollectionUpdate);
}
componentWillUnmount() {
his.unsubscribe();
}
onCollectionUpdate = (querySnapshot) => {
const dataSource = [];
querySnapshot.forEach((doc) => {
const { id, desc, zipcode, timestamp } = doc.data();
dataSource.push({
key: doc.id,
doc,
desc,
zipcode,
timestamp,
});
});
this.setState({
dataSource,
loading: false,
});
}
The above code returns absolutely nothing, even if I put a bogus collection name. Nothing runs, and I put a bunch of console.log statements but still can't see anything. I can't even tell if there is any problems connecting to Firestore.
I have not yet tried react-native-firebase module because I thought I am only doing a simple Firestore query, but at same time I am building my app natively on iOS on a Mac.
Am I supposed to be using the react-native-firebase module?
There is a typo error in your componentWillMount. componentWillUnmount() {
his.unsubscribe();
}
should be: componentWillUnmount() {
this.unsubscribe();
}
Also i recommend react-native-firebase.
So for anyone who found this with similar issues, just want to confirm that the Firebase Web SDK is indeed possible to be used for Firestore. There is no need to use react-native-firebase if your use case is very simple CRUD.
My error was that it was pulling the database content just that my render function was not displaying it.

Firestore (4.10.1): Could not reach Firestore backend. Firestore Access Issues In Cloud Functions

Quick question. Long story short, I am getting this error in my google cloud functions log:
Firestore (4.10.1): Could not reach Firestore backend.
Here is my code in my functions file:
// pull in firebase
const firebase = require('firebase');
// required
require("firebase/firestore");
// initialize firebase
const firebaseApp = firebase.initializeApp({
// Firebase configuration.
apiKey: "<Key Here>",
authDomain: "<Auth Domain>",
databaseURL: "<database url>",
projectId: "<project id>",
storageBucket: "<storage bucket>",
messagingSenderId: "<messaging sender id>"
});
// setup the firestore
var fs = firebaseApp.firestore();
exports.search = functions.https.onRequest((request, response) => {
cors(request, response, () => {
// set a reference to the foo table in firestore
var docRef = fs.collection("foo");
// check for the foo in the firestore
docRef.where('bar', '==', <something>).get().then(function(doc) {
if (!doc.docs) {
return db.collection("foo").add({
bar: <something>
})
.then(function(docRef) {
console.log("Document written with ID: ", docRef.id);
})
.catch(function(error) {
console.error("Error adding document: ", error);
});
}
});
});
});
At this point I am stuck. As far as I can tell, I have things set up, but maybe not? I have searched the docs and googled the issue, without much success. Do you see anything wrong?
All right. So the answer to my question is that I was not being very smart. A big thank you to Taha Azzabi for pointing me in the right direction. It turns out my problem was here:
docRef.where('bar', '==', <something>).get().then(function(doc) {
if (!doc.docs) {
return db.collection("foo").add({
bar: <something>
})
This would never work. My query was correct, but the check on doc.docs was incorrect. My code is now:
// setup the firestore
const fs = firebase.firestore();
// set a reference to the document for the searched summoner
var docRef = fs.collection("bars").doc("snickers");
// check for the bar in the firestore
return docRef.get()
.then(function(doc) {
if (!doc.docs) {
return fs.collection("bars").doc("snickers").set({
name: "snickers"
})
.then(function(reference) {
console.log("Document written");
return response.status(200).send('');
})
This is what I was looking for so I am good to go. Long story short, I was grabbing a collection of results then trying to check to see if a single result existed. What I needed to do was grab a single doc from the firestore and from there check to see if the single doc existed. However, the error:
Firestore (4.10.1): Could not reach Firestore backend.
Didn't really do a very good job at pointing me in that direction.
Did you install the Firebase CLI ?
npm install -g firebase-tools
Did you log in to the Firebase console through the CLI ?
firebase login
Did you initialize Firebase Cloud Functions ?
firebase init functions
You don't need then to reinitialize the app, initialize an admin app instance,thought.
Here's an example hope that will help
const functions = require('firebase-functions')
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)
//trigger a function to fire when new user document created
exports.createUser = functions.firestore
.document('users/{userId}')
.onCreate(event => {
// perform desired operations ...
});
to deployer your functions
firebase deploy --only functions
read more here https://firebase.google.com/docs/functions/get-started

Any way to use Firebase google authentication in expo (create-react-native-app) without "eject" project

As the question, for Login with google in firebase need to set google-service but if you create new react-native project with create-react-native-app there will have no "android" or "ios" folder (accept used "eject") so, anyone have a suggestion for me?
However I've no idea for how to setting google-service in my project too (even I "eject" the project).
#brentvatne 's answer is a bit out of date. Here's how I got it working on Expo v27
Important bit: you can get your client ids with these instructions.
Just select your firebase app from the project dropdown on the google page.
const _loginWithGoogle = async function() {
try {
const result = await Expo.Google.logInAsync({
androidClientId:"YOUR_ANDROID_CLIENT_ID",
iosClientId:"YOUR_iOS_CLIENT_ID",
scopes: ["profile", "email"]
});
if (result.type === "success") {
const { idToken, accessToken } = result;
const credential = firebase.auth.GoogleAuthProvider.credential(idToken, accessToken);
firebase
.auth()
.signInAndRetrieveDataWithCredential(credential)
.then(res => {
// user res, create your user, do whatever you want
})
.catch(error => {
console.log("firebase cred err:", error);
});
} else {
return { cancelled: true };
}
} catch (err) {
console.log("err:", err);
}
};
It isn't necessary to make any changes to the android or ios folders in order to support Google sign in with firebase on an app built with Expo.
Follow the guide for configuring Google auth on the Expo docs
Use the approach described in Expo's Using Firebase guide, where it describes how to authenticate with Facebook, and swap out Google where needed.

Resources