How I got Expo and react-native-firebase working in one project?

I got used to use Expo. It has many useful, ready to use libraries and an awesome Client app. Recently I’ve been working on React Native app, which used Firebase Cloud Firestore as main database.

Update 12/2020: Some parts of this article may be outdated, however the main idea of using both native and web Firebase SDK is still worth considering — Expo team has released “EAS Build” which let users build their Bare workflow apps using their build services — this means you’ll be able to build rn-firebase apps with Expo.
The SDK version in article is 36, and current Expo SDK version is 40 — newer versions came with a few analytics providers, partial built-in Firebase support (unfortunately not for Firestore), and for user authentication you can use Expo AuthSession.

The problem

When using Expo with managed workflow, installing react-native-firebase directly is impossible, because Expo doesn’t support native modules. Expo documentation says, that we have two ways:

First way is easy, but limited (only few modules are supported) and slower, because we resign from native support and do everything in JS thread.

The second way allows me to install and use any native modules, but they will not work in Expo Client. When there are only few components that use native modules, that is not a big deal, but the problem starts when whole app is using on native modules. Also, we cannot use Expo build service to build and release our app.

Which one I chose? Both. I’m not using remote Expo build services, but for testing purposes it is convenient for me to use their Client. Expo has a workaround, that allows me to use proper version of Firebase SDK:

The Solution

Fortunately, both Web and Mobile Firebase SDK has exactly same API for some modules (for example Firestore). This means we can write whole code once and it should work with both versions.

Expo allows us to create separate code files for client-specific fallbacks. Let’s create two files. One for native:

//firebaseProvider.tsconsole.log('Using Native Firestore Provider');import firestoreNative from '@react-native-firebase/firestore';

export default firestoreNative;

and one with .expo appended to its filename:

//firebaseProvider.expo.tsconsole.log('Expo - Using Node.js Firestore provider');
import * as firebase from 'firebase'; import 'firebase/firestore';
const firebaseConfig = {
"apiKey": "===<<<YOUR_API_KEY>>>===",
"authDomain": "===<<<PROJECT_ID>>>===.firebaseapp.com",
"projectId": "===<<<PROJECT_ID>>>==="
};
firebase.initializeApp(firebaseConfig);
const db = firebase.firestore();
export default () => db;

Now, we can use Firestore anywhere in our app:

import firestore from './firebaseProvider';//example usage
const items = await firestore().collection('items').get();

Loader will automatically choose which file it should import. Of course we also need to have both Firebase SDKs installed (see their official docs for installation instructions).

What with native-only Firebase modules?
Expo still allows to disable them using simple if statements. Quick example:

import analytics from '@react-native-firebase/analytics';//don't track screens for Expo Client - Firebase Web SDK 
//doesn't support it
if (appConstants.appOwnership !== AppOwnership.Expo)
analytics().setCurrentScreen(routeName, routeName);

Project creation and Android build hell

You will probably encounter some problems, when trying to build Expo Bare app with Firebase on Android. They are caused by incompatible Gradle wrapper versions. Expo bare workflow uses react-native-unimodules which require older Gradle versions to build, and react-native-firebase works with newer Gradle versions. This may lead to frustrating build errors.

By trial and error method, I have it working for Gradle wrapper version 5.0. I do not guarantee that it will work for existing projects (so make your backup before doing anything), but I will explain how to create new project and configure it to work:

Used versions: Expo 36.0, Expo CLI: 3.13.8, React-Native: 0.61,

expo init <<your project name>>
---- then select Bare Workflow (with TypeScript if you prefer) ---

2. After project generation, go into its directory and install Firebase dependencies (both web and native):

cd <<your project name>>
yarn add @react-native-firebase/app @react-native-firebase/firestore @react-native-firebase/auth firebase
---- For mac/iOS only ----
cd ios && pod install && cd ..

3. Modify Gradle configuration (generated one is corrupt).

Enthusiast of electronics and all kinds of software development — from web apps to embedded systems.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store