react-native-firebase icon indicating copy to clipboard operation
react-native-firebase copied to clipboard

[🐛] 🔥 remote config method `fetchAndActivate()` inconsistent with method `fetch()` and then `activate()` on iOS only

Open JDMathew opened this issue 3 months ago • 3 comments

Issue

If you call await fetchAndActivate() remote config method on iOS it always returns a true value, even when new values were not fetched from the remote. This value contradicts the value returned by activate() when values were not fetched. A code snipped below can be used to test this:

 async function fetchAndActivateCompare() {
  const lastFetch = await remoteConfig().lastFetchStatus;
  console.log('Last fetch status: ', lastFetch);
  await remoteConfig().fetch();
  await remoteConfig()
    .activate()
    .then((didFetch) => {
      if (didFetch) {
        console.log('RemoteConfigs fetched from fetch and then activate.');
      } else {
        console.log('RemoteConfigs not fetched from fetch and then activate.');
      }
    });
    
  await new Promise((res) => setTimeout(res, 1000));

  const fetchedRemotely = await remoteConfig().fetchAndActivate()
  if (fetchedRemotely) {
    console.log('RemoteConfigs fetched from fetchAndActivate.');
  } else {
    console.log('RemoteConfigs not fetched from fetchAndActivate');
  }
}

// call init in useEffect somewhere in your app
const init = async () => {

  // set config
  await remoteConfig()
        .setConfigSettings({
          minimumFetchIntervalMillis: 500, // NOTE 500 milliseconds is less than our set time out, allowing for a sufficient cache reset before calling `fetchAndActivate()`
        })
      
  await fetchAndActivateCompare();   

}

This results in the following output in the console:

 LOG  Last fetch status:  success
 LOG  RemoteConfigs not fetched from fetch and then activate.
 LOG  RemoteConfigs fetched from fetchAndActivate.

Project Files

Javascript

Click To Expand

package.json:

# N/A

firebase.json for react-native-firebase v6:

# N/A

iOS

Click To Expand

ios/Podfile:

  • [ ] I'm not using Pods
  • [x] I'm using Pods and my Podfile looks like:
# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
  'require.resolve(
    "react-native/scripts/react_native_pods.rb",
    {paths: [process.argv[1]]},
  )', __dir__]).strip

platform :ios, min_ios_version_supported
prepare_react_native_project!


flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled

linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
  Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
  use_frameworks! :linkage => linkage.to_sym
end

target 'AOT' do
  config = use_native_modules!

  # Flags change depending on the env values.
  flags = get_default_flags()

  # Firebase needs to use frameworks see react-native-firebase docs
  use_frameworks! :linkage => :static
  $RNFirebaseAsStaticFramework = true

  use_react_native!(
    :path => config[:reactNativePath],
    # Hermes is now enabled by default. Disable by setting this flag to false.
    :hermes_enabled => flags[:hermes_enabled],
    :fabric_enabled => flags[:fabric_enabled],
    ## Enables Flipper.
    ##
    ## Note that if you have use_frameworks! enabled, Flipper will not work and
    ## you should disable the next line. (DISABLED FLIPPER FOR USE WITH FRAMEWORKS NEEDED FOR FIREBASE)
    # :flipper_configuration => flipper_config,
    ## An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/.."
  )

  target 'AOTTests' do
    inherit! :complete
    # Pods for testing
  end


  post_install do |installer|

    # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
    react_native_post_install(
      installer,
      config[:reactNativePath],
      :mac_catalyst_enabled => false
    )
    __apply_Xcode_12_5_M1_post_install_workaround(installer)

  end
end

AppDelegate.mm:

#import "AppDelegate.h"
#import "RNBootSplash.h" // react-native-bootsplash
#import <Firebase.h> // Setup for Firebase services with react-native-firebase

#import <React/RCTBundleURLProvider.h>

// CUSTOM IMPORTS
#import <CodePush/CodePush.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [FIRApp configure]; // Setup for Firebase services with react-native-firebase
  self.moduleName = @"AOT";
  // You can add your custom initial props in the dictionary below.
  // They will be passed down to the ViewController used by React Native.
  self.initialProps = @{};

  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
  return [CodePush bundleURL]; // <--- Replaced for CodePush Previous: (return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];)
#endif
}

// ⬇️ This method will need to change for react-native-bootsplash to work on 0.74+ versions. See docs
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
                          moduleName:(NSString *)moduleName
                           initProps:(NSDictionary *)initProps {
  UIView *rootView = [super createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
  [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView]; // ⬅️ initialize the splash screen (RN boot splash)
  return rootView;
}
// ⬆️ This method will need to be removed and change to:
// - (void)customizeRootView:(RCTRootView *)rootView {
//   [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView]; // ⬅️ initialize the splash screen
// }

@end


Android

Click To Expand

Have you converted to AndroidX?

  • [ ] my application is an AndroidX application?
  • [ ] I am using android/gradle.settings jetifier=true for Android compatibility?
  • [ ] I am using the NPM package jetifier for react-native compatibility?

android/build.gradle:

// N/A

android/app/build.gradle:

// N/A

android/settings.gradle:

// N/A

MainApplication.java:

// N/A

AndroidManifest.xml:

<!-- N/A -->

Environment

Click To Expand

react-native info output:

 System:
  OS: macOS 14.4
  CPU: (10) arm64 Apple M1 Pro
  Memory: 208.44 MB / 32.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 18.17.0
    path: ~/.nvm/versions/node/v18.17.0/bin/node
  Yarn:
    version: 1.22.21
    path: ~/.nvm/versions/node/v18.17.0/bin/yarn
  npm:
    version: 9.6.7
    path: ~/.nvm/versions/node/v18.17.0/bin/npm
  Watchman:
    version: 2023.09.25.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.13.0
    path: /opt/homebrew/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.4
      - iOS 17.4
      - macOS 14.4
      - tvOS 17.4
      - visionOS 1.1
      - watchOS 10.4
  Android SDK: Not Found
IDEs:
  Android Studio: 2022.1 AI-221.6008.13.2211.9619390
  Xcode:
    version: 15.3/15E204a
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.10
    path: /usr/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.72.4
    wanted: 0.72.4
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false
  • Platform that you're experiencing the issue on:
    • [x] iOS
    • [ ] Android
    • [ ] iOS but have not tested behavior on Android
    • [ ] Android but have not tested behavior on iOS
    • [ ] Both
  • react-native-firebase version you're using that has this issue:
    • ^19.2.2
  • Firebase module(s) you're using that has the issue:
    • remote config
  • Are you using TypeScript?
    • Y & 5.0.4

JDMathew avatar May 05 '24 09:05 JDMathew