Use Firebase remote config with Expo

1 minute read

Firebase JS SDK does not support Remote Config by default1. The only way to use it is to eject from Expo and use a bare project with React Native Firebase.

Refactoring the current project to use a different approach is challenging, so we prefer to stay with Expo.


To use Firebase Remote Config, we can follow the instructions, but this leads to the first problem:

firebaseerror: remote config: indexed db is not supported by current browser (remoteconfig/indexed-db-unavailable).

IndexedDB

IndexedDB is a low-level API for client-side storage of significant amounts of structured data, including files/blobs2. Currently, React Native (RN) does not support IndexedDB3.

Mock

We can use fakeIndexedDB4 to override window.indexedDB to simulate its presence.

1
import "fake-indexeddb/auto";

This leads to another error:

structuredClone is not defined

structuredClone

structuredClone is one of the Non-ECMAScript JS APIs5, but it is required for fakeIndexedDB, We can mock this in the environment as well.

1
2
import { cloneDeep } from "lodash";
window.structuredClone = cloneDeep;

Firebase Error

We can now continue with Firebase, but another error occurs when calling the fetchAndActivate function:

failed to fetch and activate remote config FirebaseError: Installations: Could not process request. Application offline.

This happens because Firebase checks navigator.onLine to ensure the app is online:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
if (installationEntry.registrationStatus === RequestStatus.NOT_STARTED) {
  if (!navigator.onLine) {
    // Registration required but app is offline.
    const registrationPromiseWithError = Promise.reject(
      ERROR_FACTORY.create(ErrorCode.APP_OFFLINE)
    );
    return {
      installationEntry,
      registrationPromise: registrationPromiseWithError
  };
}

navigator.onLine returns the online status of the browser6. In this project, this value is false, so we can override it to ensure our app appears online.

1
2
// @ts-expect-error: navigator.onLine must be true
window.navigator["onLine"] = true;

It works

Finally, restart your project, and it should work!