Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Firestore offline persistence not working on react native #436

Closed
santiarias opened this issue Jan 15, 2018 · 38 comments
Closed

Firestore offline persistence not working on react native #436

santiarias opened this issue Jan 15, 2018 · 38 comments

Comments

@santiarias
Copy link

when enabling persistence I get an error on react native:

import * as firebase from 'firebase';
require("firebase/firestore");
firebase.firestore().enablePersistence();

Error enabling offline storage. Falling back to storage disabled: FirebaseError: [code=unimplemented]: This platform is either missing IndexedDB or is known to have an incomplete implementation. Offline persistence has been disabled.

When reading https://firebase.google.com/docs/firestore/manage-data/enable-offline
I see:

Note: Offline persistence is supported only in Android, iOS, and web apps.
and
Important: For the web, offline persistence is an experimental feature that is supported only by the Chrome, Safari, and Firefox web browsers. Also, if a user opens multiple browser tabs that point to the same Cloud Firestore database, and offline persistence is enabled, Cloud Firestore will work correctly only in the first tab.

I assume that is the reason why that is not working on react native, if so, could you confirm. Is this in the pipeline?

@google-oss-bot
Copy link
Contributor

Hey there! I couldn't figure out what this issue is about, so I've labeled it for a human to triage. Hang tight.

@google-oss-bot
Copy link
Contributor

Hmmm this issue does not seem to follow the issue template. Make sure you provide all the required information.

@merlinnot
Copy link
Contributor

You might want to use https://rnfirebase.io instead. It works really well.

@santiarias
Copy link
Author

Hi,

Thanks, sadly that library requires manual linking to native code for ios / android, which I think it goes against the "write once, run everywhere" mentality that react native is trying to achieve.
Furthermore that library does not work with Expo which is bundled and used by default by react native
(ie https://facebook.github.io/react-native/docs/getting-started.html)

@cloudprogrammer
Copy link

You can just eject from expo and still use the expo sdk if you wanna use its tools. And the manual linking is required, its a small caveat to the react native process. You link then you write JS code once that runs on Android or iOS.

@philohelp
Copy link

The best solution would be to enable offline persistance within react-native. Are there any structural problems to achieve this or should we consider that it's only a matter of time ?

@matthiaw
Copy link

Hi All,
i try to use firestore wirth react-native, redux and expo. It works fine in the online version. See https://github.com/matthiaw/react-native-redux-example/tree/d91d38adb2f376dc3a22825482668de3ad8ccf63.

But it throws an exception when i want to enable offline-persistence. See the given code in my repo to test it.

Can anyone name a working offline-persistence for firestore with react-native and expo?

@dfreire
Copy link

dfreire commented Jan 30, 2018

According to the docs:

  • For Android and iOS, offline persistence is enabled by default. To disable persistence, set the PersistenceEnabled option to false.
  • For the web, offline persistence is disabled by default. To enable persistence, call the enablePersistence method. Cloud Firestore's cache isn't automatically cleared between sessions. Consequently, if your web app handles sensitive information, make sure to ask the user if they're on a trusted device before enabling persistence.

https://firebase.google.com/docs/firestore/manage-data/enable-offline

Can you try not calling enablePersistence()and check if offline persistence works?
(I mean, using https://rnfirebase.io)

@samtstern
Copy link
Contributor

It's been a while since there has been any activity on this issue, so I am going to close it.

While we want to support using Firestore everywhere in a flexible manner, right now our only recommended usage method for React Native is through react-native-firebase, as some commenters have already said.

Please give that library a try, and raise issues on that repository if persistence does not work.

@jurosh
Copy link

jurosh commented Mar 17, 2018

😢 @samtstern react-native-firebase isn't for everyone. Current and probably the only proper way how to use Firebase in Expo is through web SDK - all other options would need app to be ejected what is something what most Expo devs doesn't want to do as it's it leads to loosing many benefits and simplicity of expo package.

Would be really great if there would be way, or at least some workaround how to make persistence work without need to use native modules.

@santiarias
Copy link
Author

Thanks @jurosh
@samtstern The reason why there was no activity no this thread, is because there was never an official response from the team for this issue.

I only got responses that did not address the issue.

I think @jurosh explained my point really well.
Using react-native-firebase makes Expo, the most used open source toolchain built around React Native, unusable. Which is recommended in the official documentation of react native

@wilhuff
Copy link
Contributor

wilhuff commented Mar 17, 2018

I'm no expert in react-native, but you're welcome to try making changes here:

https://github.com/firebase/firebase-js-sdk/blob/master/packages/firestore/src/local/simple_db.ts#L96

This is the logic that determines whether or we allow offline persistence on the platform. Just as a test you could force that method to return true. If it works try to come up with some narrower test that allows persistence to proceed in this environment.

As I understand it though with a brief search, react-native does not support IndexedDB, which is why that function returns false today. From what I can find they expect you to use their own AsyncStorage API. This is no small undertaking and not anything we can take on. We'd welcome a community contribution that implemented it and would be happy to help integrate it, but we're stretched thin already and can't do this work ourselves.

You might also try to find something to polyfill IndexedDB, similar to IndexedDBShim though that makes no mention of AsyncStorage support so I'm not hopeful for that particular one.

So unless react-native actually supports IndexedDB and our test is just wrong, our advice stands: if you want offline persistence you have to use react-native-firebase.

@mohshraim
Copy link

not expert with react native..

On iOS if react-native using webview where IndexedDB not implemented so firestore persistence will not work.
if they use WKWebview then should presiste successfully...

again don't know much about react native but i think you should give a try using this;
https://github.com/CRAlpha/react-native-wkwebview

share with us the result :)

@SourceCipher
Copy link

SourceCipher commented Jun 26, 2018

I tried multiple times to enable persistence on react native but failing each time.. I tried doing it via settings like firebase.firestore().settings({ persistence: true }) but that wont work as well.

The weirdest thing about this is if I run my app offline, all works well, images loading instantly, everything is kept as it was from the last launch, but as soon as I relaunch with the wifi on, all the data is being loaded from the back end and it takes sometimes 5s for the image to appear.. Its a very big issue for me and I have no idea how to solve

@philohelp
Copy link

philohelp commented Jun 26, 2018 via email

@SourceCipher
Copy link

@philohelp I am not using expo

@agates4
Copy link

agates4 commented Oct 27, 2018

https://github.com/sunnylqm/react-native-storage

can't this be used to plug into the local storage that firebase is using? shouldn't be hard to implement that library to create a solution that works for expo..

@nandorojo
Copy link

Is there any plan to add offline persistence for Expo?

@mikelehen
Copy link
Contributor

@nandorojo We don't currently have plans to invest in making our Web SDK offline support work in React Native. Would it be possible to use the native (Android / iOS) Firestore SDKs instead? I believe Expo supports that to some degree now. https://blog.expo.io/using-firebase-in-expo-e13844061832

@nandorojo
Copy link

nandorojo commented May 5, 2019

Hey @mikelehen, thanks for getting back to me. The article you attached is for detached Expo projects only unfortunately, so it doesn't work with managed Expo projects.

I understand there's no plan for this now, but I think it would be amazing if you decided to add support for RN offline. Many apps are moving towards RN (above all, Expo) and offline support is a central draw of using Firestore.

I believe JS libraries like redux-persist use localStorage on web and AsyncStorage on RN out of the box. I assume the same could be done for Firestore using pure JS without much trouble.

From the article you sent:

We started building expo-firebase based off of react-native-firebase in order to attempt to get it to work well within the Expo client. It turned out that there wasn’t a good way to do this — the SDK fully expects that there is one binary per app, and the Expo client has multiple apps inside of it. We weren’t able to work around this. If you’d like to use Firebase in the Expo client with the managed workflow, we’d recommend using the Firebase JS SDK.

Really hoping this gets added to plans for support. Thanks again for your help!

@wilhuff
Copy link
Contributor

wilhuff commented May 5, 2019

My previous response on this topic still stands.

React Native's AsyncStorage and react-native-async-storage are simple key-value stores with just get/put operations. These are insufficient for implementing Firestore: we rely on being able to scan keys in order using range scans to implement queries.

Essentially, until it's possible to polyfill IndexedDB on top of React Native, there's no way we can support offline persistence there.

@nandorojo
Copy link

Thanks for clarifying. While I'm not familiar with how IndexedDB works, if I could come up with an implementation for React Native, would offline persistence then be supported?

@mikelehen
Copy link
Contributor

@nandorojo Yes! It should just automatically work if IndexedDB was available (

if (typeof window === 'undefined' || window.indexedDB == null) {
).

@zwily
Copy link

zwily commented Sep 1, 2019

I hesitate to share this because of how hacky it all seems, but I did manage to get Firestore persistence working in an Expo app with the firebase web SDK:

https://gist.github.com/zwily/e9e97e0f9f523a72c24c7df01d889482

I wouldn't ship anything with that without a ton of testing (I've only done about an hour's worth). It does appear to be feasible though!

@SourceCipher
Copy link

I actually disabled firebase persistance and doing it all myself using realm local db. Its super fast and it acts like a bridge between your user and firebase db

@nandorojo
Copy link

nandorojo commented Sep 2, 2019

@SourceCipher Do you have an example of how to implement that? Do all firestore persistence features work?

So far I've been storing all of my firestore data in redux, and using redux-persist to have it cache. I'm not sure if this is optimal, though. Would be great to be able to actually use the offline persistence as intended instead of adding a whole new step for redux.

@zwily Thank you for passing along the gist, I'll give it a try tonight!

@zwily
Copy link

zwily commented Sep 2, 2019

@nandorojo Let me know how it goes. I haven't run into any problems while testing my app today, and it's nice having everything loading so quickly...

@nandorojo
Copy link

@zwily Seems to work (with a slight lag). Will do more tests throughout the night to figure out if the lag is in my render code or not and if there are any bugs. This is great work. I’ll do what I can to make sure it’s ready for production.

Also, is it worth adding a check for the react native platform in case the user is on expo web?

@smontlouis
Copy link

@zwily Thank you SO much ! Working like a charm !

@smontlouis
Copy link

@zwily haha I was too quick to talk :

On Android

Uncaught Error: console.error: "Firestore (6.3.5) INTERNAL UNHANDLED ERROR: Could not evaluate a key from keyPath and there is no key generator"

@nandorojo
Copy link

nandorojo commented Sep 11, 2019

@zwily haha I was too quick to talk :

On Android

Uncaught Error: console.error: "Firestore (6.3.5) INTERNAL UNHANDLED ERROR: Could not evaluate a key from keyPath and there is no key generator"

I've had no issues on iOS and have been testing for about a week so far. I'll try it out on Android too.

@bulby97 Would you mind describing the error a bit more?

Did this happen immediately on app load? Does it keep the app from working? Is your firebase.firestore().enablePersistence() wrapped in a try/catch and this is the error it gives? Does it happen both with and without connection?

@nandorojo
Copy link

nandorojo commented Sep 16, 2019

I've tested @zwily's solution on Android and get the same error as @bulby97. It keeps the app from working at all. For now I'm trying if (Platform.OS === 'ios') instead.

@schmidt-sebastian
Copy link
Contributor

@nandorojo @bulby97 @zwily We are actually using IndexedDbShim as our testing layer during development. While I certainly don't recommend that anyone should ship an actual app using this, it has been relatively reliable (other than the fact that is is a little on the slow side). See https://github.com/firebase/firebase-js-sdk/blob/3c8f85d0185e3305f0ba7790d46eebb8e9e78e62/packages/firestore/test/util/node_persistence.ts

@nandorojo
Copy link

@schmidt-sebastian Thanks for the heads up! I'll test it out.

For now, @zwily's solution seems to work on iOS, though I'm still testing speeds for it.

Given the high levels of investment in react native/expo from the community, I hope that at some point the firebase team considers a similar pure-JS workaround for persistence on react native.

@nandorojo
Copy link

@zwily Perhaps there is a better place to put these errors, but I got this randomly on iOS:

Screen Shot 2019-09-19 at 10 37 18 AM

Seems to be a SQLite error of sorts, not sure what the cause is.

@JCBsystem
Copy link

JCBsystem commented Sep 24, 2019

setting the autoIncrement to true
in the './node_modules/indexeddbshim/dist/indexeddbshim-noninvasive'
makes
Uncaught Error: console.error: "Firestore (6.3.5) INTERNAL UNHANDLED ERROR: Could not evaluate a key from keyPath and there is no key generator"
go away

but i can not figure out how to set it by override
can only do it by hard code it to true in the code base.

@agates4
Copy link

agates4 commented Sep 24, 2019

been following this thread for a year..

would love to see android implementation

@zaptrem
Copy link

zaptrem commented Oct 4, 2019

Same here. Does that hack support Android @zwily ?

@firebase firebase locked and limited conversation to collaborators Oct 23, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests