React-native-firebase: Offline persistence after app restart

Created on 6 Apr 2017  路  24Comments  路  Source: invertase/react-native-firebase

Currently I had an issue about offline persistence (on iOS)
First I call an update request (while offline) like

firebase.database()
    .ref('my_ref')
    .set(myData)
    .then(() => {
      resolve('Synchronization success');
    })
    .catch(err => {
      reject('Synchronization fail');
    })

I'm sure that firebase had store myData locally (I can get value from my_ref) and after app gains connection again or soft restart (tap Home button -> tap App icon to reopen), myData is uploaded to remote. But when app is completely shut down (double tap Home button -> swipe App away) then reopen, Firebase doesn't upload myData

Is this a wrong behavior or am I missing something?

Most helpful comment

@Leeds-eBooks afaik .keepSynced() prevents it from being evicted out the persistent disk cache, the disk cache has a maximum capacity of 10mb, if that's reached evictions of stale/least used data is done. Without it but with persistence enabled it still will work - unless the cache is full and it gets evicted. And of course it will keep the data fresh, whereas without it persisted data is only updated when accessed via a ref.

All 24 comments

Have you tried this?

const ref = firebase.database().ref('my_ref');
ref.keepSynced(true);

ref.set(myData).then().catch();

I was struggling to work our what .keepSynced() actually does but I just found this.

So in other words, is it true to say that offline won't really be useful unless we use .keepSynced()?

I've tried . keepSynced() but it doesn't work @Ehesp, same behavior.

Okay, what about when you initilize the module?

Firebase.initializeApp({
  debug: __DEV__ ? '*' : false,
  errorOnMissingPlayServices: false,
  persistence: true, // <<<<<<<<<<<<<<<<<<<<
});

@Leeds-eBooks afaik .keepSynced() prevents it from being evicted out the persistent disk cache, the disk cache has a maximum capacity of 10mb, if that's reached evictions of stale/least used data is done. Without it but with persistence enabled it still will work - unless the cache is full and it gets evicted. And of course it will keep the data fresh, whereas without it persisted data is only updated when accessed via a ref.

I initialize as setup doc:

import RNFirebase from 'react-native-firebase'

// Config
const firebase = new RNFirebase({
  debug: true,
  persistence: true
});

export default firebase

@Salakar so you mean whenever app is opened, we must check firebase local database and update un-updated records?

I believe internally in our app we use redux-persist to keep the data from firebase in redux. Even offline redux gets updated, so when the app boots we just re-sync it back up with firebase.

Its probably worth checking, somehow, whether the native SDKs will sync on app reboot. If they do, then there's an issue we need to sort.

From Firebase doc

When persistence is enabled, this queue is also persisted to disk so all of your writes are available when the user or operating system restarts the app.

I do believe Firebase native SDK can handle syncing offline data after app is shut down and reopened. Can you make a quick check about this issue? Or do you know how to check firebase un-synced local records? I'll need this way to fix this issue temporarily.

@dzuncoi is this on android or ios that you're having a problem with?

Can you try in your main application constructor call:

firebase.database().setPersistence(true);

If its android then i think it might be a race condition relating to https://github.com/invertase/react-native-firebase/blob/master/docs/firebase-setup.md

@Salakar I'm having problem on iOS, both simulator and device.
Hmm, I cannot use firebase.database().setPersistence(true); because setPersistence() is not a function and I don't find setPersistence method inside database class.

@dzuncoi Have you tried to reinstall the app after initializing the firebase?
Its working fine for me even if I restarted the App.

@bakr-baroudi yes, I tried to reinstall everything and it still doesn't work correctly. Did you completely shut down app and restart, then Firebase automatically sync data for you?

I don't know if I'm missing something but after my app is restarted, I need to execute a request and Firebase, then, will sync all un-updated data for me. Is that a correct behavior or Firebase should automatically do that work?

yes @dzuncoi, Its working for me.

  • How I tested this use case:
    1- Switch to offline mode.
    2- Add some data to my app.
    3- Close the App.
    4- Connect to Network.
    5- Launch the App wait for few seconds. (Syncing)
    6- Data is available in both remote and local databse.

Hi @bakr-baroudi, at step 3, Close the App., do you let it run in the background, or totally kill it (for ex on iOS: double tab Home > swipe App thumbnail away)? Your approach also works for me if I don't kill the app

@dzuncoi You need to add an event Listener to your path data.

  • In this event I am listening to adding data:
listenForAddingItems() {
        this.userRef.on('child_added',  (snap) => {
            console.log(snap)
            this.items.push({ id: snap.key, ...snap.val()});
            this.setState({
                dataSource: this.state.dataSource.cloneWithRows(this.items)
            });
        });
  } 

please check this

@dzuncoi I totally close the App.

Oh man, you made my day @bakr-baroudi. Never think of I should add listener to my path. Thank you so much

I'm getting the same issue on Android using [email protected]
After pushing new data offline the state is persisted, if I kill the app and restart it, I still can see the data. But as soon as I get the app online looks like the sync process deletes the data entered offline. Tried .keepSynced(true) to no avail.
Looks like killing the app messes up the ability of the sync process to reconcile the online and local state.

Thinking of implementing something similar to what @Ehesp described but syncing data manually opens up another area for errors and unforeseen scenarios.
Would upgrading to 3.1.x help?
Any suggestions would be appreciated

EDIT:
Looks like upgrading to 3.1.0 solved the issue for me

@raduflp can you confirm 3.1.0 definitely works for you? I'm seeing no persistence of data submitted when offline and app closed (killed) or device restarted before re-connecting, even if I re-trigger a push to the same refs after I restart the app...

It fixed the issue on Android, but in my app I still have this issue on iOS Release build only.
At the same time I could not reproduce the issue using the example app, so it must be a configuration issue with my project or maybe some weird incompatibilities with other packages when the code is minified.

I'll investigate a bit more in the next couple of days and I'll get back to you

@bakr-baroudi, @dzuncoi

can you please explain bit more on the below code, how it will work if i totally close the my app? for example in offline mode am trying to push some data into firebase using .push() and closed my app, so will the data get push while reopen my app with online mode?

am using firebase from 'react-native-firebase';

listenForAddingItems() {
this.userRef.on('child_added', (snap) => {
console.log(snap)
this.items.push({ id: snap.key, ...snap.val()});
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.items)
});
});
}

For anyone looking to enable offline persistence in rn-firebase

Enabling database persistence (setPersistence) via JS for the default app is no longer supported. This breaking change was made in v3.0.0 to avoid race condition issues. You can still however easily enable this natively for the default app instance:

https://rnfirebase.io/docs/v4.0.x/core/default-app#Enable-Database-Persistence

Android
Add FirebaseDatabase.getInstance().setPersistenceEnabled(true); inside your MainApplication.java files onCreate() method.

You also need to explicitly add the FirebaseDatabase import with the rest of the imports near the top of your MainApplication.java file:

import com.google.firebase.database.FirebaseDatabase;COPY

iOS
Add [FIRDatabase database].persistenceEnabled = YES; after the [FIRApp configure]; line inside your AppDelegate.m files didFinishLaunchingWithOptions method.

I tried hundreds of ways to get the react native to work offline but it never does.. The problem is with the cache management.. On native android it will always load everything from the cache if exists and then updates the data after looking at the db, on react native it never happens like that.. It always will show no data and then either loads from cache or db..

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bitfabrikken picture bitfabrikken  路  52Comments

TalEliel picture TalEliel  路  48Comments

gilbert picture gilbert  路  65Comments

tranty9597 picture tranty9597  路  79Comments

umang-simform picture umang-simform  路  77Comments