Firebase SDK with Firestore for React Native apps in 2018
At Firebase Dev Summit 2017, Google introduced Firestore as fully-managed NoSQL document database for mobile and web app development. Compared to Firebase Realtime Database, it has better querying and more structured data, together with ease manual fetching of data.
The new structure of collection and document is probably the eye catching, this makes data more intuitive to users and query a breeze.
In this post, I will show how to setup Firebase Cloud Firestore in React Native apps for both iOS and Android through, of course, some pain points. Then we create and fetch document in Firestore database.
Firebase Javascript SDK
My first option is to go with Firebase Javascript SDK, as it worked well for me with Firebase Realtime Database. My use case is to just fetch and update Firestore collections, I think it does not involve much of native features. Furthermore, when possible I try to avoid native code as much as possible when dealing with React Native.
So let’s try Get started with Cloud Firestore
npm install firebase
The version I install is 5.4.0. Next, import firebase
and note that we need to import firestore
as well
const firebase = require("firebase");
// Required for side-effects
require("firebase/firestore");
document is not defined
This issue made me bang against my desk for a while. As people have pointed out, it is because of document being accessed.
var BrowserPlatform = /** @class */ (function () {
function BrowserPlatform() {
this.emptyByteString = '';
this.document = document; // delete this line
this.window = window; // delete this line
this.base64Available = typeof atob !== 'undefined';
}
The firestore
component in the current Firebase Javascript SDK does not fully support React Native, so we need to work around or use beta version with npm install firebase@next
. In the mean time, let’s try React Native Firebase.
React Native Firebase
Reading over at Cloud Firestore Library and framework integrations, React Native Firebase is recommended. Although some features from the Firebase Web SDK will generally work with React Native, it is mainly built for the web and as such has a limited compatible feature set.
The below article and their starter app is the guiding star. The integration with native code in iOS and Android can be painful, but I React Native Firebase is very powerful as it has up-to-date wrappers around native Firebase SDK.
Let ‘s npm install react-native-firebase
, the current version is 4.3.8
, and follow manual setup guide for existing project, this helps you learn more about the process and the bootstrap script.
A quick look
First you need to Firebase console and add a project. A project allows many apps to stay, for example I have 4 apps (2 iOS, 2 Android) that have access to Firestore database.
Head over to Database
in the left menu, we can see a quick look into Firestore and its collection/document structure
Setup for iOS
Follow iOS Installation Guide
Firstly, download GoogleService-Info.plist and place it in the correct folder, make sure it has been added to project via Xcode. Otherwise Firebase SDK causes app to crash right after start.
Then add #import <Firebase.h>
to AppDelegate.m
and [FIRApp configure];
to function didFinishLaunchingWithOptions
. Next create Podfile
with pod init
inside ios
folder. For Firestore, you need Firebase/Firestore
to prevent the error below
You attempted to use a firebase module that’s not installed natively on your iOS project by calling firebase.firestore()
And you shouldn’t use use_frameworks!
as it gives error ‘FirebaseCore/FIRAnalyticsConfiguration.h’ file not found
platform :ios, '9.0'target 'FoodshopGuest' do
pod 'Firebase/Core', '~> 5.3.0'
pod 'Firebase/Firestore', '~> 5.3.0'
end
If you get framework not found FirebaseAnalytics
, then make sure each target has $(inherited)
at the top for Framework Search Paths
Then run react-native link react-native-firebase
and you should be good for iOS.
Setup for Android
Android is a bit less straightforward to setup than iOS. But it’s not impossible. Let’s follow Android Installation guide.
Firstly, place google-services.json
in android/app/google-services.json
. Let’s also use Gradle 4.4
and Google Play Services 15.0.1
. Change gradle/gradle-wrapper.properties
to use
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
Below is my project build.gradle
with compileSdkVersion 27
and buildToolsVersion 27.0.3
. Make sure google()
stays above jcenter()
// Top-level build file where you can add configuration options common to all sub-projects/modules.buildscript {
repositories {
mavenLocal()
google()
jcenter()
maven {
url 'https://maven.google.com/'
name 'Google'
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.3'
classpath 'com.google.gms:google-services:4.0.1'// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}allprojects {
repositories {
mavenLocal()
google()
jcenter()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
}
}ext {
buildToolsVersion = "27.0.3"
minSdkVersion = 16
compileSdkVersion = 27
targetSdkVersion = 26
supportLibVersion = "26.1.0"
}
For my app module build.gradle
, let’s have apply plugin: ‘com.google.gms.google-services’
at the very bottom of the file, this is important. In dependencies
section, you must have com.google.firebase:firebase-firestore
to include Firestore component.
dependencies {
implementation project(':react-native-firebase')
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"// Firebase dependencies
implementation "com.google.android.gms:play-services-base:15.0.1"
implementation "com.google.firebase:firebase-core:16.0.1"
implementation "com.google.firebase:firebase-firestore:17.0.2"}
Make sure there is no duplication of project(‘:react-native-firebase’)
. And since we are using Gradle 4, let’s use implementation
instead of compile
Because of Firestore, let’s follow react-native-firebase-starter
to fix heap problem
dexOptions {
javaMaxHeapSize "4g"
}multiDexEnabled true
If you get Native module RNFirebaseModule tried to override FNFirebaseModule
Native module RNFirebaseModule tried to override FNFirebaseModule for module name Firebase. If this was your intention, set `canOverrideExistingModule=true
Then make sure your MainApplication.java
has no duplication for new RNFirebasePackage()
. Here is my MainApplication.java
, note that you need import io.invertase.firebase.firestore.RNFirebaseFirestorePackage;
in order to use RNFirebaseFirestorePackage
package com.fantageek.foodshophost;import android.app.Application;import com.facebook.react.ReactApplication;
import io.invertase.firebase.RNFirebasePackage;
import io.invertase.firebase.firestore.RNFirebaseFirestorePackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;import java.util.Arrays;
import java.util.List;public class MainApplication extends Application implements ReactApplication {private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNFirebasePackage(),
new RNFirebaseFirestorePackage()
);
}@Override
protected String getJSMainModuleName() {
return "index";
}
};@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
}
My rule of thumb is that you should always use Android Studio to perform Gradle sync
or Build project
There you should be able to see compile issues much easier. With all the steps above, compilation should succeed.
One problem with running React Native on Android, if after react-native run-android
and Metro keeps showing Loading dependency graph, done
, then you should start emulator via Android Studio -> AVD Manager
or adb
, the app should be already installed in the emulator, open the app and Metro will start loading again.
Trying Firestore
React Native Firebase should give you similar APIs to those in the web, so learn from Get data with Cloud Firestore for how to get
or set
documents.
I like to organise services in separate files, here is how to reference firestore
and load document.
import firebase from 'react-native-firebase'class FirebaseService {
constructor() {
this.ref = firebase.firestore().collection('people')
}async load(id) {
const doc = await this.ref.doc(id).get()
if (doc.exists) {
return doc.data()
} else {
const defaultDoc = {
name: "ABC",
age: 2
}await this.ref.doc(id).set(defaultDoc)
return doc
}
}
}export const firebaseService = new FirebaseService()
Where to go from here
I hope this article helps in setting up Firebase SDK in React Native apps. Below are some resources that helps you explore further. The react-native-firebase-starter
contains awesome reference code if you get into any troubles with react-native-firebase
.
❤️ Support my app ❤️
- Push Hero — pure Swift native macOS application to test push notifications
- PastePal — Pasteboard, note and shortcut manager
- Frame recorder — Recorder gif and video with frame
- Alias — App and file shortcut manager
- Other apps
❤️❤️😇😍🤘❤️❤️