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.64k stars 2.21k forks source link

[REALTIME DATABASE PERSISTENCE] persistence is not working well in realtime database #4411

Closed HasanSahabGlobal closed 3 years ago

HasanSahabGlobal commented 3 years ago

as mentioned in docs, persistence is enabled by default, it is not working. it is working only if enabled manually by "database().setPersistenceEnabled(false)" function, it works well (persists data and works offline). but, this STOPS receiving updates from online Firebase database. (This issue appears on both platforms).

package.json:

  "dependencies": {
    "@dudigital/react-native-zoomable-view": "^1.0.15",
    "@react-native-community/async-storage": "^1.9.0",
    "@react-native-community/hooks": "^2.6.0",
    "@react-native-community/masked-view": "^0.1.7",
    "@react-native-community/netinfo": "^5.9.2",
    "@react-native-community/push-notification-ios": "^1.3.0",
    "@react-native-firebase/analytics": "^7.6.8",
    "@react-native-firebase/app": "^8.4.6",
    "@react-native-firebase/auth": "^9.3.1",
    "@react-native-firebase/database": "^7.5.12",
    "@react-native-firebase/messaging": "^7.9.1",
    "@react-native-firebase/perf": "^7.4.9",
    "@react-navigation/bottom-tabs": "^5.6.1",
    "@react-navigation/material-top-tabs": "^5.2.12",
    "@react-navigation/native": "^5.6.1",
    "@react-navigation/stack": "^5.6.2",
    "axios": "^0.19.2",
    "clevertap-react-native": "^0.4.5",
    "i18next": "^19.4.3",
    "libphonenumber-js": "^1.7.51",
    "lodash": "^4.17.19",
    "lottie-ios": "^3.1.8",
    "lottie-react-native": "^3.4.0",
    "moment": "^2.27.0",
    "react": "16.11.0",
    "react-hook-form": "^5.3.1",
    "react-i18next": "^11.3.5",
    "react-native": "0.62.0",
    "react-native-adjust": "^4.22.0",
    "react-native-animatable": "^1.3.3",
    "react-native-confirmation-code-field": "^6.0.0",
    "react-native-device-info": "^5.6.1",
    "react-native-drop-shadow": "^0.0.2",
    "react-native-easy-content-loader": "^0.3.2",
    "react-native-fast-image": "^8.1.5",
    "react-native-flags": "^1.0.0",
    "react-native-gallery-swiper": "^1.26.4",
    "react-native-gesture-handler": "^1.6.1",
    "react-native-keyboard-aware-scroll-view": "^0.9.1",
    "react-native-masked-text": "^1.13.0",
    "react-native-outlined-input": "https://hasan_1995@bitbucket.org/hasan_1995/react-native-material-outlined-input.git",
    "react-native-paper": "4.0.0-alpha.0",
    "react-native-push-notification": "^4.0.0",
    "react-native-reanimated": "^1.7.1",
    "react-native-restart": "^0.0.17",
    "react-native-safe-area-context": "^0.7.3",
    "react-native-screens": "^2.9.0",
    "react-native-share": "^3.7.1",
    "react-native-splash-screen": "^3.2.0",
    "react-native-svg": "^12.1.0",
    "react-native-svg-flagkit": "^0.9.5",
    "react-native-swiper": "^1.6.0",
    "react-native-tab-view": "^2.14.4",
    "react-native-vector-icons": "^6.6.0",
    "react-native-webview": "^10.7.0",
    "yup": "^0.28.3"
  },
  "devDependencies": {
    "@babel/core": "^7.9.0",
    "@babel/runtime": "^7.9.2",
    "@react-native-community/eslint-config": "^1.0.0",
    "@storybook/addon-actions": "^5.3.18",
    "@storybook/addon-links": "^5.3.18",
    "@storybook/addons": "^5.3.18",
    "@storybook/react-native": "^5.3.18",
    "@storybook/react-native-server": "^5.3.18",
    "@types/i18n-js": "^3.0.2",
    "@types/jest": "^25.2.1",
    "@types/lodash": "^4.14.158",
    "@types/react": "^16.9.32",
    "@types/react-native": "^0.62.1",
    "@types/react-native-dotenv": "^0.2.0",
    "@types/react-native-push-notification": "^3.0.9",
    "@types/react-native-share": "^3.3.0",
    "@types/react-native-vector-icons": "^6.4.5",
    "@types/react-test-renderer": "^16.9.2",
    "@types/styled-components": "^5.1.0",
    "@types/yup": "^0.26.36",
    "axios-mock-adapter": "^1.18.1",
    "babel-jest": "^25.2.6",
    "babel-loader": "^8.1.0",
    "eslint": "^6.8.0",
    "jest": "^25.2.7",
    "metro-react-native-babel-preset": "^0.59.0",
    "react-dom": "16.11.0",
    "react-native-dev-menu": "^4.0.2",
    "react-native-dotenv": "^0.2.0",
    "react-native-typescript-transformer": "^1.2.13",
    "react-test-renderer": "16.11.0",
    "reactotron-react-native": "^5.0.0",
    "ts-jest": "^25.3.1",
    "typescript": "^3.8.3"
  },
  "jest": {
    "preset": "react-native",
    "transformIgnorePatterns": [
      "node_modules/(?!(jest-)?react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|sentry-expo|native-base|react-native-svg|@expo/vector-icons|clevertap-react-native|@dudigital)"
    ],
    "setupFilesAfterEnv": [
      "<rootDir>/__mocks__/mockFirebase.js"
    ],
    "setupFiles": [
      "./node_modules/react-native-gesture-handler/jestSetup.js",
      "./__mocks__/testenv.js",
      "./__mocks__/react-native-device-info.js"
    ],
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js"
    ],
    "moduleNameMapper": {
      "\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
      "\\.(css|less)$": "<rootDir>/mocks/fileMock.js"
    },
    "moduleDirectories": [
      "node_modules",
      "src"
    ]
  }
}

firebase.json:

{
    "react-native": {
        "messaging_android_notification_color": "@color/crimson"
    }
}
mikehardy commented 3 years ago

Hi @HasanSahabGlobal - my best advice is to trace through (via adding logging output perhaps) the code directly in node_modules in the parts that handle the init sequence in order to see exactly how the config is being set / when it is being set so you can see how and why things are configured the way they are during initialization. That can then serve as the basis for making a pull request to fix the issue - the init sequence hops across a couple of objects if I recall correctly but is not hard to trace. While working on the PR, the https://github.com/ds300/patch-package utility can be used to make sure any changes you create that get things working for you are easily distributed among your whole team and are easy to track etc (it really is a fantastic utility)

If you find that the configuration appears to be doing everything correctly then this will have to be tracked into the upstream firebase-android-sdk and firebase-ios-sdk libraries, each of those have "quickstart" projects that let you quickly create a reproducible demonstration of the problem so you can file a ticket with google firebase team for official support

HasanSahabGlobal commented 3 years ago

resolved by "keepSynced" but i think it is not an optimal solution.

        const ref = database().ref(path);

        /**
         * keep it synced.
         */
        await ref.keepSynced(true);

        /**
         * get document by ref.
         */
        const document: FirebaseDatabaseTypes.DataSnapshot = await ref.once('value');

        /**
         * return val from document.
         */
        return document;
stale[bot] commented 3 years ago

Hello 👋, to help manage issues we automatically close stale issues. This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?

This issue will be closed in 15 days if no further activity occurs. Thank you for your contributions.

stale[bot] commented 3 years ago

Closing this issue after a prolonged period of inactivity. If this is still present in the latest release, please feel free to create a new issue with up-to-date information.

nes123 commented 3 years ago

Experiencing the same problem. Offline persistent and the use of ".once" is not predictable.

mikehardy commented 3 years ago

@nes123 if you can provide an App.js we could drop in a project and use to trigger this we might be able to track it down...

nes123 commented 3 years ago

My understanding after reading many discussions on that is that this is the intended behavior of the SDK. If persistence is enabled SingeEvent Snapshot will read from the local database. If sync is needed you must use keepSynced(true)

Very non-intuitive and making migration of an online to offline somehow complicated.

mikehardy commented 3 years ago

That is non-intuitive, I don't know the database behavior well enough to have known that in advance. This seems like something that could be a note on the API for toggling persistence - maybe also .once or keepsynced - there are edit buttons for a quick web-based PR flow on the top right of all the general usage and specific API docs if you can think of a good place to put this. A link back to any of the upstream docs that mention it would be gold too, could probably save others a lot of confusion

nes123 commented 3 years ago

A good solution to this problem will be to use the new method in the SDK:

public Task get ()

Gets the server values for this query. Updates the cache and raises events if successful. If not connected, falls back to a locally-cached value.


Any ideas if it is implemented in react-native-firebase?

mikehardy commented 3 years ago

I'd be happy to work with you on a PR @nes123! Please post one up and we can get it merged here

nes123 commented 3 years ago

https://github.com/invertase/react-native-firebase/pull/5328#issue-646115251

nes123 commented 3 years ago

I started something. I have zero experience in native programming so it is very naive. Please feel free to assist. I will work on that again tomorrow.