invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.71k stars 2.22k forks source link

[🐛] Realtime Database Not Working #4864

Closed RomanScott closed 3 years ago

RomanScott commented 3 years ago

Issue

Hello. I am using Realtime Database on Android, but for some reason, I'm not receiving any of the callbacks of my read / write events. For example, here is what one of my code snippets looks like to isolate the error:

import database from '@react-native-firebase/database';

const db = database()

let userInfo = await db.ref("users/" + userUUID).once("value")

And this causes the app to wait indefinitely. No error is being emitted from this code either. Another example is when I try to use a listener:

db.ref("users/" + userUUID).on("value", console.log).catch((error) => console.log(error))

Which also doesn't do anything. I have the database set to read and write world, so I don't think it's a security problem. I think the problem has to do with the JS callback not being invoked from the native bridge, because data is being written to the database (when I do a set() function, the data is written).

However, I do see one error being shown in Logcat, but am not sure if it's related to this issue or not.

E/unknown:ReactContextBaseJavaModule: Unhandled SoftException
    java.lang.RuntimeException: Catalyst Instance has already disappeared: requested by WebSocketModule
        at com.facebook.react.bridge.ReactContextBaseJavaModule.getReactApplicationContextIfActiveOrWarn(ReactContextBaseJavaModule.java:67)
        at com.facebook.react.modules.websocket.WebSocketModule.sendEvent(WebSocketModule.java:62)
        at com.facebook.react.modules.websocket.WebSocketModule.access$100(WebSocketModule.java:40)
        at com.facebook.react.modules.websocket.WebSocketModule$1.onMessage(WebSocketModule.java:190)
        at okhttp3.internal.ws.RealWebSocket.onReadMessage(RealWebSocket.java:323)
        at okhttp3.internal.ws.WebSocketReader.readMessageFrame(WebSocketReader.java:219)
        at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:105)
        at okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.java:274)
        at okhttp3.internal.ws.RealWebSocket$2.onResponse(RealWebSocket.java:214)
        at okhttp3.RealCall$AsyncCall.execute(RealCall.java:206)
        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)

Here is a related thread for this issue: https://github.com/facebook/react-native/issues/28992 and it seems someone else who was using Realtime Database ran into the same problem.

While this issue happens about 90% of the time, there are some instances where the data is successfully loaded and the callback is received. However, this seems to be rare and is very sporadic. What is the issue here? For reference, I am using Expo SDK 40.

Thank you!


Project Files

Javascript

Click To Expand

#### `package.json`: ```json { "scripts": { "start": "react-native start", "android": "react-native run-android", "ios": "react-native run-ios", "web": "expo start --web" }, "dependencies": { "@expo/vector-icons": "^12.0.0", "@react-native-async-storage/async-storage": "^1.13.4", "@react-native-community/masked-view": "0.1.10", "@react-native-community/netinfo": "5.9.7", "@react-native-firebase/analytics": "^10.5.1", "@react-native-firebase/app": "^10.5.0", "@react-native-firebase/auth": "^10.5.1", "@react-native-firebase/crashlytics": "^10.5.1", "@react-native-firebase/database": "^10.5.1", "@react-native-firebase/functions": "^10.5.1", "@react-native-firebase/messaging": "^10.5.1", "@react-native-firebase/perf": "^10.5.1", "@react-navigation/bottom-tabs": "^5.11.3", "@react-navigation/native": "^5.9.0", "@react-navigation/stack": "^5.13.0", "expo": "^40.0.0", "expo-app-loading": "^1.0.1", "expo-apple-authentication": "~2.2.2", "expo-asset": "~8.2.1", "expo-blur": "~8.2.2", "expo-contacts": "~8.6.0", "expo-font": "~8.4.0", "expo-linear-gradient": "~8.4.0", "expo-network": "~2.4.0", "expo-payments-stripe": "~8.4.0", "expo-permissions": "~10.0.0", "expo-sms": "~8.4.0", "expo-splash-screen": "~0.8.1", "expo-status-bar": "~1.0.3", "expo-updates": "~0.4.1", "firebase-functions": "^3.3.0", "lottie-react-native": "~2.6.1", "mobx": "^5.14.0", "mobx-react": "^6.1.4", "moment": "^2.24.0", "native-base": "^2.13.8", "payment": "^2.3.0", "react": "16.13.1", "react-dom": "16.13.1", "react-native": "0.63.4", "react-native-animatable": "^1.3.3", "react-native-calendars": "^1.229.0", "react-native-credit-card-input": "^0.4.1", "react-native-datepicker": "^1.7.2", "react-native-gesture-handler": "~1.8.0", "react-native-progress": "^4.1.2", "react-native-reanimated": "~1.13.0", "react-native-safe-area-context": "3.1.9", "react-native-screens": "~2.15.0", "react-native-storage": "^1.0.1", "react-native-swiper": "^1.6.0-rc.3", "react-native-unimodules": "~0.12.0", "react-native-web": "~0.13.12" }, "devDependencies": { "@babel/core": "~7.9.0", "@testing-library/react-native": "^5.0.2", "@types/react": "~16.9.35", "@types/react-native": "~0.63.2", "babel-jest": "~25.2.6", "babel-preset-expo": "8.3.0", "jest": "~25.2.6", "react-test-renderer": "~16.13.1", "typescript": "~4.0.0" }, "private": true, "name": "App", "version": "1.0.0" } ``` #### `firebase.json` for react-native-firebase v6: ```json { "firestore": { "rules": "firestore.rules" }, "hosting": { "public": "public", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ] }, "storage": { "rules": "storage.rules" }, "functions": { "predeploy": [ "npm --prefix \"$RESOURCE_DIR\" run lint", "npm --prefix \"$RESOURCE_DIR\" run build" ], "source": "functions" } } ```

iOS

Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like: ```ruby # N/A ``` #### `AppDelegate.m`: ```objc // N/A ```


Android

Click To Expand

#### Have you converted to AndroidX? - [X ] my application is an AndroidX application? - [X ] I am using `android/gradle.settings` `jetifier=true` for Android compatibility? - [X ] I am using the NPM package `jetifier` for react-native compatibility? #### `android/build.gradle`: ```groovy // N/A ``` #### `android/app/build.gradle`: ```groovy // N/A ``` #### `android/settings.gradle`: ```groovy // N/A ``` #### `MainApplication.java`: ```java // N/A ``` #### `AndroidManifest.xml`: ```xml ```


Environment

Click To Expand

**`react-native info` output:** ``` OUTPUT GOES HERE ``` - **Platform that you're experiencing the issue on**: - [ ] iOS - [ ] Android - [ ] **iOS** but have not tested behavior on Android - [X] **Android** but have not tested behavior on iOS - [ ] Both - **`react-native-firebase` version you're using that has this issue:** - 6 - **`Firebase` module(s) you're using that has the issue:** - `e.g. Instance ID` - **Are you using `TypeScript`?** - Y


mikehardy commented 3 years ago

Curiously, I'm in the same area and have noticed some issues with once as I've been trying to get the database emulator supported officially #4854 - the problem I'm having is with a once on .info/connected special node not returning the correct value, but I did not see problems with once returning itself.

The best I can recommend is to check out the repo, then follow the README in the tests directory - find the e2e test set that has the most similar tests compared with your use case and set this to describe.only (vs describe) and then execute them. This should prove things are working or get you a great workbench for exactly what is not working. I think the .once stuff is actually returning fine, the only problem I'm having is the connected status :thinking:

piccinnigius commented 3 years ago

@RomanScott any advice on how to manage it?

angel-discover commented 3 years ago

facing the exact same issue. Might be some incompatibility with expo SDK 40 (I'm running in bare workflow). Anyone have any workarounds for RTDB?

mikehardy commented 3 years ago

The only way to know if it is an incompatibility with expo or not is to run a clean RNFB project with a minimal reproducible App.js: https://github.com/mikehardy/rnfbdemo/blob/master/make-demo.sh

mikehardy commented 3 years ago

no response - needs reproduction for forward progress

ghivert commented 3 years ago

Hi, I just wanted to let you know that I experienced the same problems with React Native Firebase v12 on iOS 14.5. Had to downgrade to v11.5 to make it work again after hours of fight to understand what's happening. I can try to provide a MRE next week. For information, I'm using the special node .info/connected, but also classic once, and none got fired. It feels like a problem of Firebase Pod because the JS code is running fine and executing correctly but the callback is never called (or the promise is never fullfilled).

mikehardy commented 3 years ago

I have seen some some issues with .info/connected and sometimes the once as well. I'd love a minimal reproduction to track this down. Please note that the problem is likely below us in firebase-ios-sdk, so you might try basing a reproduction on their quickstart (should make it very easy?) to see - https://github.com/firebase/quickstart-ios/tree/master/database

michaelmika commented 2 years ago

I have the same problem with Realtime Database on Android. No promise is resolving. Not for once, set, etc. Same code works fine on iOS. Was on react-native-firebase 12.x.x and updated to latest version (14.5.0). Still I can't use any Realtime Database function on android. No error gets thrown, no promise gets resolved. I even tried to initialize the database with link (see below), although it was not necessary for iOS.

import { firebase } from '@react-native-firebase/database';

const reference = firebase
  .app()
  .database('https://<databaseName>.<region>.firebasedatabase.app/')

I think it is a real issue. Considering to move all Database Code now to Firebase Functions, although it works on all other devices.

mikehardy commented 2 years ago

@michaelmika You can thumbs down my request for a reproduction all you want, but in my experience this has been problems with other packages messing up promise behavior. I have never seen a minimal reproduction where this happened, but I have seen several (about 4 now? Maybe 5?) where the person came back and said "yeah, it turns it was redux / expo / some-other-package". That's the data I've got

The only way to know if it is an incompatibility with expo or not is to run a clean RNFB project with a minimal reproducible App.js: https://github.com/mikehardy/rnfbdemo/blob/master/make-demo.sh

I provide a complete script to kick out a clean project in order to ease the pain. Give it a shot, see if you can make the database package fail in a clean app with an App.js, if you can we have a problem and I'll check it out

michaelmika commented 2 years ago

Sorry to bother you, I just want to share my errors with this package on android and support people searching for a solution. The Promise does not resolve or reject, but I get an error on the native thread saying:

W/PersistentConnection: pc_0 - Provided authentication credentials are invalid. This usually indicates your FirebaseApp instance was not initialized correctly. Make sure your google-services.json file has the correct firebase_url and api_key. You can re-download google-services.json from https://console.firebase.google.com/.

We have included the correct google-services.json file a several times. I guess the error is because we are using multiple real time database (in different regions). We have initialized the database using

const reference = firebase
  .app()
  .database('https://<databaseName>.<region>.firebasedatabase.app/')

as in the docs. As I said, the same code works on iOS, so I inspected the google-services.json and could not find any reference to the database in there. We tried to add a custom key database_url in there with no success. I can't provide a minimal reproducable App, because the scenario is also firebase related.

My current take is to write a firebase function wrapper for the database to bypass this error/problem.

mikehardy commented 2 years ago

Interesting, @michaelmika you have not provided all the information initially, that you are using multiple RTDBs via URL is new information (https://stackoverflow.com/help/how-to-ask) - it was kind of embedded in your first comment, but not in a way that I picked up on. That's one of the reasons a single App.js file demonstrating the problem would be useful, then there is no confusion. Do not be discouraged from creating a minimum reproducible example, they are always illuminating, and there is no reason you can't create throw-away firebase projects as backends to demonstrate, it's what we do with our test project here. With no billing attached to them, there is no risk of abuse (or at least, no costs associated with possible abuse).

Have you tried digging in to node_modules and/or the native Java code to print out the customUrlOrRegion (I think I'm getting that param correct...) that is in use, so you can see how it is attempting to access the specific RTDB instance?

We do test that initializing multiple URLs works but we do not exercise multi-RTDB functionality much: https://github.com/invertase/react-native-firebase/blob/6a1753d25af40aba93b2d12e32152782ea857f9f/packages/database/e2e/database.e2e.js#L92-L103

It could be there really is an issue here, if so, opening a new issue and filling out details + having a single App.js snippet that would demonstrate it is how to get resolution. That would be much preferred to writing a functions wrapper over firebase-admin-sdk in my opinion, unless there was some side benefit in then having a kind of REST API to your database that you controlled, keeping the RTBD access off the uncontrolled clients.

michaelmika commented 2 years ago

Thanks for your reply. The value for _customUrlOrRegion is correct, but still it does not connect. Strangely, on a minimal App with the same backend, the App is able to connect, so it might have to do something with my setup. But I can't imagine what other external package could cause connection problems for only the real time database (also using firestore, auth, and many more firebase modules which are all working as expected).

I will move on with the REST API approach with functions, since it fits the usecase in my app.

zeabdelkhalek commented 2 years ago

I also have the same issue

RahulRijhwani commented 2 years ago

I found the solution actually my app exceed the firebase real time database free plan limit

Screenshot 2022-07-28 at 6 35 41 PM
alarm109 commented 1 year ago

In our case the problem was, that we were listening to the changes and after when reloading the app sometimes it would not return any values. In the firebase console we would see that the connection is still active. My hypothesis is that the listener connection was active, therefore the new connection could not be made again. We were calling off method incorrectly, so my guess this was the problem.

const onValueChange = databaseRef.on(
      'value',
      snapshot => emit({ user: snapshot.val() }),
);

// We were not calling off method correctly
// return () => databaseRef.off();
// instead of
return () => databaseRef.off('value', onValueChange);