facebook / metro

🚇 The JavaScript bundler for React Native
https://metrobundler.dev
MIT License
5.21k stars 621 forks source link

React-Native ERROR Invariant Violation: `new NativeEventEmitter()` requires a non-null argument., "myApp" has not been registered. iOS only #1125

Closed thomasaugot closed 9 months ago

thomasaugot commented 12 months ago

We are facing issues when trying to build our app on iOS only. An entire week trying everything and now we are just checking package after package, and yet still unable to find a solution... All packages are up to date, it builds perfectly on Android, but iOS will build successfully yet throw the error:

ERROR Invariant Violation: `new NativeEventEmitter()` requires a non-null argument., js engine: hermes LOG Running "myApp" with {"rootTag":41,"initialProps":{}} ERROR Invariant Violation: "myApp" has not been registered. This can happen if: * Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project. * A module failed to load due to an error and `AppRegistry.register component` wasn't called., js engine: hermes

We have tried deleting the Pods, Podfile.lock, deleting node modules, npm install --force, pod install, pod update, even pod deintegrate, pod init, everything we found a bit everywhere on Google, nothing ever worked. We are sure of the app name "myApp" , as you can see in the following files:

/**
* Metro configuration for React Native
* [https://github.com/facebook/react-native](https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ffacebook%2Freact-native&data=05%7C01%7C%7C7d0de339685e4d3773ae08dbd644cc13%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C638339363183246835%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=E6SSblrcUZf7r5o9IpyunXzXFziWbJ6M3Hc%2FfKv%2BFis%3D&reserved=0)
*
* @format
*/

module.exports = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
resolver: {
sourceExts: ['jsx', 'js', 'ts', 'tsx', 'cjs', 'json'],
},
};

System: OS: macOS 12.6.8 CPU: (4) x64 Intel(R) Core(TM) i5-5350U CPU @ 1.80GHz Memory: 652.14 MB / 8.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 20.4.0 - /usr/local/bin/node Yarn: Not Found npm: 9.7.2 - /usr/local/bin/npm Watchman: 2023.07.10.00 - /usr/local/bin/watchman Managers: CocoaPods: 1.12.1 - /Users/armandpetit/.rvm/gems/ruby-2.7.4/bin/pod SDKs: iOS SDK: Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1 Android SDK: Not Found IDEs: Android Studio: 2022.2 AI-222.4459.24.2221.9862592 Xcode: 14.2/14C18 - /usr/bin/xcodebuild Languages: Java: 11.0.18 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 18.2.0 => 18.2.0 react-native: 0.71.6 => 0.71.6 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found

/////// Index.js /**
 * @format
 */

import {AppRegistry} from 'react-native';
import App from './App';

AppRegistry.registerComponent('myApp', () => App);
/////// package.json
{
  "name": "myApp",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios --simulator=\"iPhone 14\"",
    "clean": "rm -rf node_modules && npm i",
    "hard-clean-ios": "cd ios && rm -rf Pods && rm -rf build && pod cache clean --all && pod install && cd ..",
    "hard-clean-android": "rm -rf node_modules && npm i && cd android && ./gradlew clean && cd ..",
    "delete-cache": "watchman watch-del-all && rm -rf $TMPDIR/react-* && rm -rf $TMPDIR/metro-* && rm -rf $TMPDIR/haste-* && rm -rf node_modules/ && npm cache clean --force && npm install && npm start -- --reset-cache",
    "lint": "eslint .",
    "start": "react-native start",
    "test": "jest",
    "clean:ios": "rm -rf ios/build"
  },
  "reactNativePermissionsIOS": [
    "BluetoothPeripheral",
    "FaceID",
    "LocationAccuracy",
    "LocationAlways",
    "LocationWhenInUse"
  ],
  "dependencies": {
    "@react-native-async-storage/async-storage": "^1.19.3",
    "@react-native-community/checkbox": "^0.5.16",
    "@react-native-community/netinfo": "^9.4.1",
    "@react-native/metro-config": "^0.74.0",
    "@react-navigation/bottom-tabs": "^6.5.9",
    "@react-navigation/native": "^6.1.8",
    "@react-navigation/native-stack": "^6.9.14",
    "date-fns": "^2.30.0",
    "lottie-react-native": "^6.3.1",
    "moment": "^2.29.4",
    "react": "18.2.0",
    "react-native": "0.72.4",
    "react-native-base64": "^0.2.1",
    "react-native-ble-plx": "^3.0.0",
    "react-native-bluetooth-state-manager": "^1.3.5",
    "react-native-config": "^1.5.1",
    "react-native-date-picker": "^4.3.3",
    "react-native-device-info": "^10.11.0",
    "react-native-flash-message": "^0.4.2",
    "react-native-gradle-plugin": "^0.71.19",
    "react-native-location-enabler": "^4.1.1",
    "react-native-permissions": "^3.9.3",
    "react-native-rename": "^3.2.13",
    "react-native-safe-area": "^0.5.1",
    "react-native-safe-area-context": "^4.7.2",
    "react-native-screens": "^3.25.0",
    "react-native-splash-screen": "^3.3.0",
    "react-native-vector-icons": "^9.2.0",
    "react-native-version": "^4.0.0"
  },
  "devDependencies": {
    "@babel/core": "^7.23.0",
    "@babel/preset-env": "^7.22.20",
    "@babel/runtime": "^7.23.1",
    "@react-native-community/eslint-config": "^3.2.0",
    "@tsconfig/react-native": "^2.0.3",
    "@types/jest": "^29.5.5",
    "@types/react": "^18.2.28",
    "@types/react-native-base64": "^0.2.0",
    "@types/react-native-vector-icons": "^6.4.15",
    "@types/react-test-renderer": "^18.0.3",
    "babel-jest": "^29.7.0",
    "eslint": "^8.51.0",
    "jest": "^29.7.0",
    "metro-react-native-babel-preset": "^0.73.9",
    "prettier": "^2.8.8",
    "react-test-renderer": "18.2.0",
    "typescript": "4.8.4"
  },
  "jest": {
    "preset": "react-native"
  }
}
////// Podfile

require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

platform :ios, min_ios_version_supported
prepare_react_native_project!

# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
#
# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js`
# ```js
# module.exports = {
#   dependencies: {
#     ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}),
# ```
flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled

# use_frameworks!

target 'myApp' do
  config = use_native_modules!

  permissions_path = '../node_modules/react-native-permissions/ios'

  pod 'Permission-FaceID', :path => "#{permissions_path}/FaceID"
  pod 'Permission-LocationAccuracy', :path => "#{permissions_path}/LocationAccuracy"
  pod 'Permission-LocationAlways', :path => "#{permissions_path}/LocationAlways"
  pod 'Permission-LocationWhenInUse', :path => "#{permissions_path}/LocationWhenInUse"

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

  use_react_native!(
    :path => config[:reactNativePath],
    # Hermes is now enabled by default. Disable by setting this flag to false.
    # Upcoming versions of React Native may rely on get_default_flags(), but
    # we make it explicit here to aid in the React Native upgrade process.
    :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.
    :flipper_configuration => flipper_config,
    # An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/.."
  )

  # pre_install do |installer|
  #   Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}

  #   installer.pod_targets.each do |pod|
  #     if pod.name.eql?('RNPermissions') || pod.name.start_with?('Permission-')
  #       def pod.build_type;
  #         # Uncomment the line corresponding to your CocoaPods version
  #         # Pod::BuildType.static_library # >= 1.9
  #         # Pod::Target::BuildType.static_library # < 1.9
  #       end
  #     end
  #   end
  # end

  ENVFILES = {
  'Debug' => '$(PODS_ROOT)/../../.env.dev',
  'Release' => '$(PODS_ROOT)/../../.env.prod',
}

  post_install do |installer|
    react_native_post_install(
      installer,
      # Set `mac_catalyst_enabled` to `true` in order to apply patches
      # necessary for Mac Catalyst builds
      :mac_catalyst_enabled => false
    )
    installer.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
        if target.name == 'react-native-config'
          config.build_settings['ENVFILE'] = ENVFILES[config.name]
        end
      end
    end
    __apply_Xcode_12_5_M1_post_install_workaround(installer)
  end
end
/////// AppDelegate.mm
#import "AppDelegate.h"

#import <React/RCTBundleURLProvider.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  self.moduleName = @"myApp";
  // 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 [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

/// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
///
/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
/// @return: `true` if the `concurrentRoot` feature is enabled. Otherwise, it returns `false`.
- (BOOL)concurrentRootEnabled
{
  return true;
}

@end

Can't figure out what we are missing. Any help would be amazing :)

lansanalsm commented 9 months ago

Hey @thomasaugot Facing the same issue. How did you resolved the issue please ?

thomasaugot commented 9 months ago

Hey @lansanalsm ! Yeah found it after a week on it! The issue came from the package "react-native-location-enabler": "^4.1.1". It is not compatible with iOS and will throw an error if not conditionally called in the app using Platform.OS === "android". I just totally removed it and the error is gone. If you don't have this one installed, check for other packages :)

lansanalsm commented 9 months ago

Thanks @thomasaugot, You're right, for me it was firebase-* packages, i removed them and the error is gone ! Happy new year