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

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

Update 07/2021: This article has become outdated and the solution described . I’ve written a new article describing a lot better approach to this problem. You can find it here. 🔥

The content below is outdated, I strongly discourage you from using the solutions described there. For a better solution, please see the update above.

The problem

  • Use Firebase Web JS SDK
  • Use Expo bare workflow

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:

  • When I run my app on Expo client, Firebase Web JS SDK is loaded
  • When I build it using bare react-native, Firebase native SDK is loaded

The Solution

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:

Update: Note that since Expo SDK 41 the extension .expo.ts is no longer working. More details here.

//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

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,

  1. Create new Bare Workflow expo project:
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).

  • Go to android/build.gradle and replace:
    task wrapper(type: Wrapper) with just wrapper
  • Go to android/gradle/wrapper/gradle-wrapper.properties and in distributionUrl replace version 4.10.1 (or any other) with 5.0
  • Check if it builds, run react-native run-android , react-native run-ios (mac only) and expo start .
  • Configure Firebase for your project (see Google and RN-Firebase docs)
  • Try to use solution above :)

Enthusiast of electronics and all kinds of software development — from web apps to embedded systems. Expo open-source contributor at Software Mansion.