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

🔥 firestore onSnapshot does not work when two different platform are connected to the same component #1931

Closed Manouli closed 5 years ago

Manouli commented 5 years ago

Issue

I am trying to create a chat system using react native firebase firestore.

I am facing a problem on my channel list where the snapshots don't work as expected when two different platforms are using the chat.

When an ios is using it and another ios is using too we have no issues. The same goes for android. When two android are being used the snapshots update properly.

However when I have ios with android the snapshots are not being called propely.

So this lists my channels properly

I am creating a snapshot listener inside my react native component's constructor.

this.channelRef = dbRef
      .where('users', 'array-contains', props.user)
      .orderBy('dateUpdated', 'desc');

Then inside my componentDidMount

this.channelWatcher = this.channelRef.onSnapshot(this.onChannelUpdate);

And this is the onChannelUpdate

onChannelUpdate = (snapshot) => {
    const channels = snapshot.docs.map((docSnapshot) => {
      const { users } = docSnapshot.data();

      users.map(user => this.props.load(user));

      return {
        id: docSnapshot.id,
        ...docSnapshot.data(),
      };
    });

    this.props.setChannels(channels);
  };

When I have the same platform it works smoothly. When I have two different platforms it removes the channels that get updated depending on which platform is updating the channels. So if android updates the channel Android would then see the channel and the iOS won't and the opposite is happening as well. Any ideas what could be causing this?

I am pretty sure that that this is a package specific issue because its not happening on the web.


Project Files

iOS

ios/Podfile:

target 'fitii' do
  pod 'AppCenter/Crashes', '~> 1.10.0'
  pod 'AppCenter/Analytics', '~> 1.10.0'
  pod 'AppCenterReactNativeShared', '~> 1.9.0'
  pod 'React', :path => '../node_modules/react-native', :subspecs => [
    "Core",
    "ART",
    "RCTActionSheet",
    "RCTAnimation",
    "RCTCameraRoll",
    "RCTGeolocation",
    "RCTImage",
    "RCTNetwork",
    "RCTText",
    "RCTVibration",
    "RCTWebSocket",
    "DevSupport"
  ]
  pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
  pod 'Firebase/Core', '~> 5.15.0'
  pod 'Firebase/Auth', '~> 5.15.0'
  pod 'Firebase/Firestore', '~> 5.15.0'
  pod 'Firebase/Storage', '~> 5.15.0'
  pod 'Firebase/DynamicLinks', '~> 5.15.0'
  pod 'Firebase/Messaging', '~> 5.15.0'
  pod 'RNBackgroundFetch', :path => '../node_modules/react-native-background-fetch'
  pod 'RNSVG', :path => '../node_modules/react-native-svg'
  pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'
  pod 'react-native-fbsdk', :path => '../node_modules/react-native-fbsdk'
  pod 'react-native-image-picker', :path => '../node_modules/react-native-image-picker'
  pod 'RNFS', :path => '../node_modules/react-native-fs'
  pod 'AppAuth', '>= 0.94'
  pod 'react-native-video', :path => '../node_modules/react-native-video'
  # codepush
  pod 'CodePush', :path => '../node_modules/react-native-code-push'
  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
  platform :ios, '9.0'
  # end codepush
  # Pods for AppCenter
  pod 'RNLanguages', :path => '../node_modules/react-native-languages'

  pod 'ReactNativeKeyboardManager', :path => '../node_modules/react-native-keyboard-manager'

  pod 'RNGoogleSignin', :path => '../node_modules/react-native-google-signin'

  pod 'RNScreens', :path => '../node_modules/react-native-screens'

  # TEMP fix for RN Firebase
  # https://github.com/invertase/react-native-firebase/issues/1633#issuecomment-444960860
  # pod 'GoogleAppMeasurement', '~> 5.3.0'
  pod 'react-native-orientation', :path => '../node_modules/react-native-orientation'

  pod 'BugsnagReactNative', :path => '../node_modules/bugsnag-react-native'

end

post_install do |installer|
  installer.pods_project.targets.each do |target|
      if target.name == 'yoga'
          # Workaround: react-native v0.52 bug issue #17274
          # node_modules/react-native/ReactCommon/yoga/yoga/YGNodePrint.cpp:208:46: Implicit conversion loses integer
          # precision: 'size_type' (aka 'unsigned long') to 'const uint32_t' (aka 'const unsigned int')
          # https://github.com/facebook/react-native/issues/17274#issuecomment-356363557
          #target.build_configurations.each do |config|
          #    config.build_settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'NO'
          #    config.build_settings['GCC_WARN_64_TO_32_BIT_CONVERSION'] = 'NO'
          #end
          target.remove_from_project
      end
      if target.name == "RNSVG"
          target.build_configurations.each do |config|
              config.build_settings['GCC_NO_COMMON_BLOCKS'] = 'NO'
          end
      end
      if target.name == "React"
        # fix for build error
        # https://stackoverflow.com/questions/42021796/react-native-xcode-project-product-archive-fails-with-duplicate-symbols-for-arch/46678210#46678210
        target.remove_from_project
      end
  end
end

AppDelegate.m:

/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#import "AppDelegate.h"
#import <AppCenterReactNativeCrashes/AppCenterReactNativeCrashes.h>
#import <AppCenterReactNativeAnalytics/AppCenterReactNativeAnalytics.h>
#import <AppCenterReactNative/AppCenterReactNative.h>
#import <CodePush/CodePush.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <Firebase.h>
#import "RNFirebaseLinks.h"
#import "RNFirebaseNotifications.h"
#import "RNFirebaseMessaging.h"
#import <AVFoundation/AVFoundation.h>
#import "RNSplashScreen.h"
#import "RNAppAuthAuthorizationFlowManager.h"
#import "Orientation.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [FIROptions defaultOptions].deepLinkURLScheme = @"com.myproject.app";
  [FIRApp configure];
  [RNFirebaseNotifications configure];
  [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil]; // allow other apps to play audio over video in this app

  NSURL *jsCodeLocation;

  [AppCenterReactNativeCrashes registerWithAutomaticProcessing];  // Initialize AppCenter crashes

  [AppCenterReactNativeAnalytics registerWithInitiallyEnabled:true];  // Initialize AppCenter analytics

  [AppCenterReactNative register];  // Initialize AppCenter 

    #ifdef DEBUG
        jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
    #else
        jsCodeLocation = [CodePush bundleURL];
    #endif

  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                      moduleName:@"fitii"
                                               initialProperties:nil
                                                   launchOptions:launchOptions];
  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  // ADD THE FOLLOWING CODE
  NSString *filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"];
  NSDictionary *plistDict = [NSDictionary dictionaryWithContentsOfFile:filePath];
  [GIDSignIn sharedInstance].clientID = [plistDict objectForKey:@"CLIENT_ID"];
  // ADD THE ABOVE CODE

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  [RNSplashScreen show];
  return YES;
}

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {

  // Google Sign In
  BOOL handled = [[GIDSignIn sharedInstance] handleURL:url
                                     sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
                                            annotation:options[UIApplicationOpenURLOptionsAnnotationKey]];

  // Firebase Dynamic Links
  if (!handled) {
    handled = [[RNFirebaseLinks instance] application:application openURL:url options:options];
  }

  // RN App Auth
  if (!handled) {
    handled = [self.authorizationFlowManagerDelegate resumeExternalUserAgentFlowWithURL:url];
  }

  return handled;
}

- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void (^)(NSArray *))restorationHandler {
  return [[RNFirebaseLinks instance] application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
}

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
  // ADD THE FOLLOWING CODE
  if ([[GIDSignIn sharedInstance] handleURL:url
                          sourceApplication:sourceApplication
                                 annotation:annotation]) {
    return YES;
  }
  // ADD THE ABOVE CODE
  return YES;
}

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
  [[RNFirebaseNotifications instance] didReceiveLocalNotification:notification];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
  [[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
  [[RNFirebaseMessaging instance] didRegisterUserNotificationSettings:notificationSettings];
}

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
  return [Orientation getOrientation];
}

@end

Android

android/build.gradle:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        google()
        jcenter()
        maven {
            url "https://dl.bintray.com/android/android-tools/"
        }

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.0'
        classpath 'com.google.gms:google-services:3.2.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        mavenLocal()
        google()
        jcenter()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
        // Google now hosts their latest API dependencies on their own maven  server.
        // React Native will eventually add this to their app template.
        maven {
            url 'https://maven.google.com'
        }
        maven { url "https://jitpack.io" }
        maven {
            url "$rootDir/../node_modules/react-native-background-fetch/android/libs"
        }
        maven {
            url 'https://google.bintray.com/exoplayer/'
        }
        configurations.all {
            resolutionStrategy {
                force 'com.facebook.android:facebook-android-sdk:4.34.0'
            }
        }
    }
}

subprojects {
    project ->
    def name = project.name
    if (name.contains('react-native-contacts') || name.contains('react-native-image-picker')) {
        buildscript {
            repositories {
                maven { url "https://dl.bintray.com/android/android-tools/" }
            }
        }
    }
}

ext {
    buildToolsVersion = "28.0.2"
    minSdkVersion = 16
    compileSdkVersion = 27
    targetSdkVersion = 27
    supportLibVersion = "27.1.1"
    googlePlayServicesVersion = "15.0.1"
    googlePlayServicesAuthVersion = "15.0.1"
}

android/app/build.gradle:

apply plugin: "com.android.application"

import com.android.build.OutputFile

/**
 * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
 * and bundleReleaseJsAndAssets).
 * These basically call `react-native bundle` with the correct arguments during the Android build
 * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
 * bundle directly from the development server. Below you can see all the possible configurations
 * and their defaults. If you decide to add a configuration block, make sure to add it before the
 * `apply from: "../../node_modules/react-native/react.gradle"` line.
 *
 * project.ext.react = [
 *   // the name of the generated asset file containing your JS bundle
 *   bundleAssetName: "index.android.bundle",
 *
 *   // the entry file for bundle generationunified
 *   entryFile: "index.android.js",
 *
 *   // whether to bundle JS and assets in debug mode
 *   bundleInDebug: false,
 *
 *   // whether to bundle JS and assets in release mode
 *   bundleInRelease: true,
 *
 *   // whether to bundle JS and assets in another build variant (if configured).
 *   // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
 *   // The configuration property can be in the following formats
 *   //         'bundleIn${productFlavor}${buildType}'
 *   //         'bundleIn${buildType}'
 *   // bundleInFreeDebug: true,
 *   // bundleInPaidRelease: true,
 *   // bundleInBeta: true,
 *
 *   // whether to disable dev mode in custom build variants (by default only disabled in release)
 *   // for example: to disable dev mode in the staging build type (if configured)
 *   devDisabledInStaging: true,
 *   // The configuration property can be in the following formats
 *   //         'devDisabledIn${productFlavor}${buildType}'
 *   //         'devDisabledIn${buildType}'
 *
 *   // the root of your project, i.e. where "package.json" lives
 *   root: "../../",
 *
 *   // where to put the JS bundle asset in debug mode
 *   jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
 *
 *   // where to put the JS bundle asset in release mode
 *   jsBundleDirRelease: "$buildDir/intermediates/assets/release",
 *
 *   // where to put drawable resources / React Native assets, e.g. the ones you use via
 *   // require('./image.png')), in debug mode
 *   resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
 *
 *   // where to put drawable resources / React Native assets, e.g. the ones you use via
 *   // require('./image.png')), in release mode
 *   resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
 *
 *   // by default the gradle tasks are skipped if none of the JS files or assets change; this means
 *   // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
 *   // date; if you have any other folders that you want to ignore for performance reasons (gradle
 *   // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
 *   // for example, you might want to remove it from here.
 *   inputExcludes: ["android/**", "ios/**"],
 *
 *   // override which node gets called and with what additional arguments
 *   nodeExecutableAndArgs: ["node"],
 *
 *   // supply additional arguments to the packager
 *   extraPackagerArgs: []
 * ]
 */

project.ext.react = [
        entryFile: "index.js",
]

apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"

/**
 * Set this to true to create two separate APKs instead of one:
 *   - An APK that only works on ARM devices
 *   - An APK that only works on x86 devices
 * The advantage is the size of the APK is reduced by about 4MB.
 * Upload all the APKs to the Play Store and people will download
 * the correct one based on the CPU architecture of their device.
 */
def enableSeparateBuildPerCPUArchitecture = false

/**
 * Run Proguard to shrink the Java bytecode in release builds.
 */
def enableProguardInReleaseBuilds = false

android {
    compileSdkVersion rootProject.compileSdkVersion
    buildToolsVersion rootProject.buildToolsVersion
    defaultConfig {
        applicationId "com.myproject.app"
        minSdkVersion rootProject.minSdkVersion
        targetSdkVersion rootProject.targetSdkVersion
        versionCode 1
        multiDexEnabled true
        ndk {
            abiFilters "armeabi-v7a", "x86"
        }
        manifestPlaceholders = [
                appAuthRedirectScheme: 'com.myproject.app.auth'
        ]
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86"
        }
    }
    buildTypes {
        release {
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }
    // applicationVariants are e.g. debug, release
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            // For each separate APK per architecture, set a unique version code as described here:
            // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
            def versionCodes = ["armeabi-v7a": 1, "x86": 2]
            def abi = output.getFilter(OutputFile.ABI)
            if (abi != null) {  // null for the universal-debug, universal-release variants
                output.versionCodeOverride =
                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
            }
        }
    }
    compileOptions {
        sourceCompatibility 1.8
        targetCompatibility 1.8
    }
}

dependencies {
    implementation project(':react-native-audio-recorder-player')
    implementation project(':bugsnag-react-native')
    implementation project(':react-native-orientation')
    implementation project(':react-native-screens')
    implementation project(':react-native-gesture-handler')
    implementation project(':react-native-languages')
    implementation project(':appcenter-analytics')
    implementation project(':appcenter-crashes')
    implementation project(':appcenter')
    implementation project(':react-native-extra-dimensions-android')
    implementation project(':react-native-code-push')
    implementation project(':react-native-google-signin')
    implementation project(':react-native-splash-screen')
    implementation project(':react-native-video')
    implementation project(':react-native-app-auth')
    implementation project(':react-native-fs')
    implementation project(':react-native-image-picker')
    implementation project(':react-native-fbsdk')
    implementation(project(":react-native-google-signin")) {
        exclude group: "com.google.android.gms"
    }
    implementation(project(':react-native-device-info')) {
        exclude group: 'com.google.android.gms'
    }
    implementation(project(':react-native-google-fit')) {
        exclude group: 'com.google.android.gms'
    }
    implementation project(':react-native-linear-gradient')
    implementation project(':react-native-svg')
    implementation(project(':react-native-firebase')) {
        transitive = false
        exclude group: 'com.google.android.gms'
    }
    // Firebase dependencies
    implementation "com.google.android.gms:play-services-base:16.0.1"
    implementation 'com.google.android.gms:play-services-auth:15.0.1'
    implementation 'com.google.android.gms:play-services-fitness:15.0.1'
    implementation "com.google.firebase:firebase-core:16.0.6"
    implementation "com.google.firebase:firebase-firestore:17.1.5"
    implementation "com.google.firebase:firebase-auth:16.1.0"
    implementation "com.google.firebase:firebase-storage:16.0.5"
    implementation "com.google.firebase:firebase-invites:16.0.6"
    implementation "com.google.firebase:firebase-messaging:17.3.4"
    implementation 'me.leolin:ShortcutBadger:1.1.21@aar'
    // for notification badges https://rnfirebase.io/docs/v4.2.x/messaging/android
    implementation fileTree(dir: "libs", include: ["*.jar"])
    //noinspection GradleCompatible
    implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    implementation "com.android.support:support-media-compat:${rootProject.ext.supportLibVersion}"
    implementation "com.facebook.react:react-native:+"  // From node_modules
    implementation project(':react-native-background-fetch')
    // For animated GIF support
    implementation 'com.facebook.fresco:animated-gif:1.3.0'
    implementation project(':react-native-contacts')
    implementation project(':react-native-samsung-health')
}

// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.compile
    into 'libs'
}

repositories {
    flatDir {
        dirs "../../node_modules/react-native-background-fetch/android/libs"
    }
}

apply plugin: 'com.google.gms.google-services'

android/settings.gradle:

rootProject.name = 'fitii'
include ':react-native-orientation'
project(':react-native-orientation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-orientation/android')
include ':react-native-audio-recorder-player'
project(':react-native-audio-recorder-player').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-audio-recorder-player/android')
include ':react-native-screens'
project(':react-native-screens').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-screens/android')
include ':react-native-gesture-handler'
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')
include ':react-native-languages'
project(':react-native-languages').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-languages/android')
include ':appcenter-analytics'
project(':appcenter-analytics').projectDir = new File(rootProject.projectDir, '../node_modules/appcenter-analytics/android')
include ':appcenter-crashes'
project(':appcenter-crashes').projectDir = new File(rootProject.projectDir, '../node_modules/appcenter-crashes/android')
include ':appcenter'
project(':appcenter').projectDir = new File(rootProject.projectDir, '../node_modules/appcenter/android')
include ':react-native-extra-dimensions-android'
project(':react-native-extra-dimensions-android').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-extra-dimensions-android/android')
include ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
include ':react-native-google-signin'
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-signin/android')
include ':react-native-splash-screen'
project(':react-native-splash-screen').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-splash-screen/android')
include ':react-native-video'
project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android-exoplayer')
include ':react-native-app-auth'
project(':react-native-app-auth').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-app-auth/android')
include ':react-native-fs'
project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android')
include ':react-native-unified-contacts'
project(':react-native-unified-contacts').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-unified-contacts/android')
include ':react-native-image-picker'
project(':react-native-image-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-picker/android')
include ':react-native-fbsdk'
project(':react-native-fbsdk').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fbsdk/android')
include ':react-native-device-info'
project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android')
include ':react-native-google-fit'
project(':react-native-google-fit').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-fit/android')
include ':react-native-linear-gradient'
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
include ':react-native-svg'
project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android')
include ':react-native-firebase'
project(':react-native-firebase').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-firebase/android')
include ':react-native-background-fetch'
project(':react-native-background-fetch').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-background-fetch/android')
include ':react-native-contacts'
project(':react-native-contacts').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-contacts/android')
include ':react-native-samsung-health'
project(':react-native-samsung-health').projectDir = new File(settingsDir, '../node_modules/react-native-samsung-health/android')
include ':app'
include ':bugsnag-react-native'
project(':bugsnag-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/bugsnag-react-native/android')

MainApplication.java:

package com.myproject.app;

import android.app.Application;

import com.facebook.react.ReactApplication;
import com.dooboolab.RNAudioRecorderPlayerPackage;
import com.bugsnag.BugsnagReactNative;
import com.github.yamill.orientation.OrientationPackage;
import com.swmansion.rnscreens.RNScreensPackage;
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
import com.reactcommunity.rnlanguages.RNLanguagesPackage;
import com.microsoft.appcenter.reactnative.analytics.AppCenterReactNativeAnalyticsPackage;
import com.microsoft.appcenter.reactnative.crashes.AppCenterReactNativeCrashesPackage;
import com.microsoft.appcenter.reactnative.appcenter.AppCenterReactNativePackage;

import ca.jaysoo.extradimensions.ExtraDimensionsPackage;

import com.microsoft.codepush.react.CodePush;

import co.apptailor.googlesignin.RNGoogleSigninPackage;

import org.devio.rn.splashscreen.SplashScreenReactPackage;

import com.brentvatne.react.ReactVideoPackage;
import com.rnappauth.RNAppAuthPackage;
import com.rnfs.RNFSPackage;
import com.imagepicker.ImagePickerPackage;
import com.facebook.reactnative.androidsdk.FBSDKPackage;
import com.facebook.CallbackManager;
import com.learnium.RNDeviceInfo.RNDeviceInfo;
import com.reactnative.googlefit.GoogleFitPackage;
import com.BV.LinearGradient.LinearGradientPackage;
import com.horcrux.svg.SvgPackage;

import io.invertase.firebase.RNFirebasePackage;
import io.invertase.firebase.firestore.RNFirebaseFirestorePackage;
import io.invertase.firebase.auth.RNFirebaseAuthPackage;
import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage;
import io.invertase.firebase.storage.RNFirebaseStoragePackage;
import io.invertase.firebase.links.RNFirebaseLinksPackage;
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage;
import io.invertase.firebase.notifications.RNFirebaseNotificationsPackage;

import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import com.transistorsoft.rnbackgroundfetch.RNBackgroundFetchPackage;
import com.rt2zz.reactnativecontacts.ReactNativeContacts;
import com.reactnative.samsunghealth.SamsungHealthPackage;

import java.util.Arrays;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

    private static CallbackManager mCallbackManager = CallbackManager.Factory.create();

    protected static CallbackManager getCallbackManager() {
        return mCallbackManager;
    }

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {

        @Override
        protected String getJSBundleFile() {
            return CodePush.getJSBundleFile();
        }

        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
            return Arrays.<ReactPackage>asList(
                new RNBackgroundFetchPackage(),
                new LinearGradientPackage(),
                new SvgPackage(),
                new RNFirebasePackage(),
                new RNFirebaseFirestorePackage(),
                new RNFirebaseAuthPackage(),
                new RNFirebaseAnalyticsPackage(),
                new RNFirebaseStoragePackage(),
                new RNFirebaseLinksPackage(),
                new RNFirebaseMessagingPackage(),
                new RNFirebaseNotificationsPackage(),
                new MainReactPackage(),
                new RNAudioRecorderPlayerPackage(),
                new OrientationPackage(),
                new RNScreensPackage(),
                new RNGestureHandlerPackage(),
                new RNLanguagesPackage(),
                new AppCenterReactNativeAnalyticsPackage(MainApplication.this,getResources().getString(R.string.appCenterAnalytics_whenToEnableAnalytics)),
                new AppCenterReactNativeCrashesPackage(MainApplication.this, getResources().getString(R.string.appCenterCrashes_whenToSendCrashes)),
                new AppCenterReactNativePackage(MainApplication.this),
                new ExtraDimensionsPackage(),
                new CodePush(null, getApplicationContext(), BuildConfig.DEBUG),
                new RNGoogleSigninPackage(),
                new SplashScreenReactPackage(),
                new ReactVideoPackage(),
                new RNAppAuthPackage(),
                new RNFSPackage(),
                new ImagePickerPackage(),
                new FBSDKPackage(mCallbackManager),
                new RNDeviceInfo(),
                new GoogleFitPackage(BuildConfig.APPLICATION_ID),
                new ReactNativeContacts(),
                new SamsungHealthPackage(BuildConfig.APPLICATION_ID),
                BugsnagReactNative.getPackage()
            );
        }

        @Override
        protected String getJSMainModuleName() {
            return "index";
        }
    };

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this, /* native exopackage */ false);
    }
}

AndroidManifest.xml:

<!-- N/A -->

Environment


Think react-native-firebase is great? Please consider supporting the project with any of the below:

adcuz commented 5 years ago

I am having the same issue. Documents created from Android do not appear on iOS, and vice versa. Any ideas anyone?

Manouli commented 5 years ago

After spending more time debugging this it seems that when I remove this line from the code the onSnapshot works fine

Before:

this.channelRef = dbRef
      .where('users', 'array-contains', props.user)
      .orderBy('dateUpdated', 'desc');

After:

this.channelRef = dbRef
      .orderBy('dateUpdated', 'desc');

So when doing .where() the onSnapshot does not seem to work. Any ideas on how to fix that? Or maybe an alternative way?

Thanks a lot in advance.

jamosaur commented 5 years ago

Having the same issue here too 👎

Salakar commented 5 years ago

@Manouli please could you provide me with a sample of your data and a full example of the code that I can use to create a reproducible test and look if there's anything in RNFirebase causing the issue or if it's the Native SDKs.

Thanks in advance!


Loving react-native-firebase and the support we provide? Please consider supporting us with any of the below:

Manouli commented 5 years ago

@Salakar First of all thank you for getting back to me.

Here is a screenshot of data structure inside my database.

screen shot 2019-03-01 at 13 03 41

Also here is a screenshot to demonstrate that I m getting different data on the two different simulators. All 3 channels should be listed but I m getting only the ones that each simulator has created. iPhone has created 1 and Android 2.

screen shot 2019-03-01 at 13 02 57

Here is a code example to replicate this functionality. Make sure you create channels on each simulator and have them connected on the same time.

I have put some comments in the code too to help you even further but I think the example is plain enough.

Let me know if you need any further info.

Code:

import React from 'react';
import firebase from 'react-native-firebase';
import { View, FlatList, ScrollView, StyleSheet, Text } from 'react-native';

export default class ChannelList extends React.PureComponent {
  // Swap the id 88 with the id that you want to use.
  // Have to simulators running.
  // 1 for iOS and 1 for Android.
  // Create channels from each simulator.
  // Watch the snapshot bug happening.
  // Removing the .where('users', 'array-contains', 88) lists all the channels
  // Note that when we have same simulators or devices ios with ios or android
  // with android it works as expected.
  constructor(props) {
    super(props);
    this.state = {
      channels: [],
    };

    this.channelRef = firebase.firestore()
      .collection('channels')
      .where('users', 'array-contains', 88) // Swap for any id just a placeholder
      .orderBy('dateUpdated', 'desc');
    this.channelWatcher = null;
  }

  componentDidMount() {
    this.channelWatcher = this.channelRef.onSnapshot(this.onChannelUpdate);
  }

  componentWillUnmount() {
    this.channelWatcher();
  }

  onChannelUpdate = (snapshot) => {
    const channels = snapshot.docs.map(docSnapshot => ({
      id: docSnapshot.id,
      ...docSnapshot.data(),
    }));

    this.setState({
      channels,
    });
  };

  createChannel = channel => firebase.firestore()
    .collection('channels')
    .add(channel)
    .then(document => document)
    .catch((error) => {
      console.error('Error adding document: ', error);
    });

  renderChannel = item => (
    <Text>{item.name}</Text>
  );

  renderChannels = () => {
    const { channels } = this.state;
    const keyExtractor = item => `${item.id}`;
    // Create a new channel each time to test it properly with your own user ids
    // I am using 88 as my id
    const channel = {
      createdBy: {
        id: 88,
      },
      dateUpdated: new Date(),
      name: 'New channel',
      users: [88, 100],
    };

    return (
      <ScrollView style={styles.scrollView}>
        <FlatList
          keyExtractor={keyExtractor}
          data={channels}
          renderItem={({ item }) => this.renderChannel(item)}
        />

        <Text
          style={styles.addButton}
          onPress={() => this.createChannel(channel)}
        >
          Add channel
        </Text>
      </ScrollView>
    );
  }

  render() {
    return (
      <View style={{ flex: 1 }}>
        <View style={styles.messageContainer}>
          { this.renderChannels() }
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  addButton: {
    width: 200,
    padding: 10,
    textAlign: 'center',
    backgroundColor: 'green',
    color: 'white',
  },
  messageContainer: {
    flex: 1,
  },
  scrollView: {
    marginTop: 20,
    flex: 1,
  },
  channelsContainer: {
    marginTop: 20,
    flex: 1,
  },
});
stale[bot] commented 5 years ago

Hello 👋, this issue has been automatically marked as stale because it has not had activity for quite some time. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 5 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.

luco commented 5 years ago

Same here. onSnapshot doesn't work after a while.

stale[bot] commented 5 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 5 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.

cristian-milea commented 5 years ago

still having the same issue, using:

package.json
"react-native-firebase": "5.5.6"
android/app/build.gradle
implementation "com.google.firebase:firebase-firestore:19.0.0"
ehtishamali042 commented 4 years ago

its not working, same issue here, please help

mrcflorian commented 4 years ago

I'm having the same issue. I don't even use .where - it only fetches the data the first time, and there's no listening to updates.

rahulnainwal107 commented 4 years ago

I am also facing the same issue when trying to filter data based upon created_at.

mikehardy commented 4 years ago

In my experience no one has the same issue. There is always some difference in the combo of project setup, versions in use, platforms reproduced on, APIs used and code. Please open a new issue with full details and a way to reproduce the problem and we may examine