I'm using Firebase in a React Native iOS app, mainly for storing user data and user authentication, which works great when a device actually has a working network connection.
When it comes to Firebase's offline capabilities, it looks like this:
The problem: Users launching app without network connectivity can't do anything because they're never being logged in
Here are the steps to reproduce this behaviour:
Step 1: Logged-out user launches app with network connectivity
- user clicks "Facebook login" button
- Firebase logs in using Facebook auth
onAuthStateChanged (user)
is being called with the logged in user as parameter- token obtained by
user.getToken()
is sent to my server, which generates a custom token (generatedToken
) that can be used for signing into Firebase auth usingsignInWithCustomToken (generatedToken)
and is therefore saved in local storage - user happily reads and writes into Firebase database, changes are instantly synced with Firebase server
Step 2: Logged-in user launches app with network connectivity
- app realizes there's a
generatedToken
in local storage generatedToken
is used forfirebase.auth().signInWithCustomToken (..)
- (same as Step 1.3)
- (same as Step 1.4)
- (same as Step 1.5)
- Network connectivity gets lost: User is still logged in (
onAuthStateChanged (user)
is not being called withnull
as auser
, like it's the case after manually signing out) and can therefore still read & write into Firebase database - Network connectivity gets restored: Changes sync with Firebase server
Step 3: Logged-in user launches app without network connectivity
- app realizes there's a
generatedToken
in local storage generatedToken
is used forfirebase.auth().signInWithCustomToken (..)
firebase.auth().signInWithCustomToken (..)
fails, because there's not network connectiononAuthStateChanged (user)
is being called withnull
as auser
- user is not able to use Firebase database at all, since all read/write requests fails because of missing authentication
The attempted solution
Setting
persistenceEnabled
totrue
in Objective-C / AppDelegate.m, right after initializingFIRApp
:(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // ... [FIRApp configure]; [FIRDatabase database].persistenceEnabled = YES; // ... }
This doesn't lead to the desired result and (at least in my case) doesn't change anything when it comes to Firebase's behaviour.
--- YOUR SUGGESTION HERE ---
Thanks for your inputs!
Whilst the Firebase JS SDK is great and does generally work in React Native, it is mainly built for web platforms and therefore is not the most comprehensive solution for usage inside a React Native environment e.g. there are quite a few Firebase services you'll be unable to use with the Web SDK. See the comparison table here.
You can, however, run with the native Android/iOS Firebase SDKs and have a bridge between them and your JavaScript code (i.e. a react native module).
Thankfully you don't have to implement this yourself, as there are already modules out there to do this for you:
react-native-firebase for example mirrors the web SDKs API on the JavaScript side but executes on the native side using the native Android & iOS Firebase SDKs. It's compatible with any existing Firebase Web SDK logic that you may have already implemented and is intended as a drop-in replacement for the web SDK.
This library supports your use case with auth persistence and offline capabilities:
(disclaimer: I am the author of react-native-firebase)