(React Native - Using AWS Amplify) - Invariant Violation: Native module cannot be null

syumaK picture syumaK ยท Jun 2, 2020 ยท Viewed 8.3k times ยท Source

Description of the issue:

I'm implementing push notification in my React-Native app using this AWS Amplify doc and testing with the iOS part fails with the error "Invariant Violation: Native module cannot be null", however if I test (i.e fetching device token and sending push notification) the Android part it works. Screenshot of the error I see on the iOS is seen below :

enter image description here

What I have tried so far :

  1. Upgrading react-native version from 0.59.10 to 0.61.5
  2. As per this github post, I also tried installing the following:

    @react-native-community/push-notification-ios

    npm install aws-amplify@unstable

This module (aws-amplify@unstable) introduced an error ๐Ÿ˜“ saying TypeError: undefined is not an object (evaluating '_core.Amplify.register') so I decided to get rid of it.

  1. Using latest package of "@aws-amplify/pushnotification": "^3.0.13" works for Android but in iOS I'm back to the original error ๐Ÿ˜“ : "Invariant Violation: Native module cannot be null"

currently I've left my package.json as follows :

"dependencies": {
"@aws-amplify/pushnotification": "^1.1.4",
"@aws-amplify/analytics": "^1.3.3",
"@react-native-community/netinfo": "^5.7.0",
"@react-native-community/push-notification-ios": "^1.2.0",
"amazon-cognito-identity-js": "^4.2.1",
"aws-amplify": "^1.2.4",
"aws-amplify-react-native": "^4.2.0",
"axios": "^0.19.2",
"cache": "^2.3.1",
"react": "16.9.0",
"react-native": "^0.62.2"
}

Let me get some sleep, I'll continue debugging tomorrow morning ..

Answer

syumaK picture syumaK ยท Jun 5, 2020

After hours of debugging it appears some versions don't play well with each-other and I've managed to fix the error "Invariant Violation: Native module cannot be null" and get Android & iOS push notification working ๐Ÿ˜Š๐Ÿ’ช using the following version aws amplify lib and @react-native-community/push-notification-ios:

"dependencies": {
"@aws-amplify/pushnotification": "^3.0.13",
"@aws-amplify/analytics": "^1.3.3",
"@react-native-community/netinfo": "^5.7.0",
"@react-native-community/push-notification-ios": "^1.0.2",
"amazon-cognito-identity-js": "^4.2.1",
"aws-amplify": "^3.0.13",
"aws-amplify-react-native": "^4.2.0",
"axios": "^0.19.2",
"cache": "^2.3.1",
"react": "16.9.0",
"react-native": "^0.62.2"
},

or

"dependencies": {
"@react-native-community/push-notification-ios": "^1.2.0",
"@react-native-community/netinfo": "^5.7.0",
"@aws-amplify/pushnotification": "^3.1.2",
"@aws-amplify/analytics": "^1.3.3",
"@aws-amplify/core": "^3.3.2",
"amazon-cognito-identity-js": "^4.2.1",
"aws-amplify-react-native": "^4.2.0",
"aws-amplify": "^3.0.16",
"axios": "^0.19.2",
"cache": "^2.3.1",
"react": "16.9.0",
"react-native": "^0.62.2"
},

It appears AWS Amplify (push notification module for iOS) has switched from react-native core to @react-native-community/push-notification-ios. Therefore, here's some changes due to this migration which one might need to cross-check incase you run into this issue :

Step 1 : Update Podfile

Remove 'React-RCTPushNotification' from your Podfile (which you can find in ios folder).:

pod 'React-RCTPushNotification', :path => '../node_modules/react-native/Libraries/PushNotificationIOS'

Step 2: Link the PushNotificationIOS library

Step 2.1 : Automatic Linking

Add the following RNCPushNotificationIOS to your podfile (which you can find in ios folder).

pod 'RNCPushNotificationIOS', :path => '../node_modules/@react-native-community/push-notification-ios/RNCPushNotificationIOS.podspec'

And then install pod dependencies by running following command: cd ios && pod install

Step 2.2 : Manual Linking (if Auto linking doesn't work for you consider this option)

Drag this PushNotificationIOS.xcodeproj file (node_modules/@react-native-community/push-notification-ios/ios) to your project on Xcode (usually under the Libraries group on Xcode):

enter image description here

Add libRNCPushNotificationIOS.a into your linked Binaries by selecting Project Navigator -> Target -> Build Phrases -> Linked Binary with Libraries (make sure libRNCPushNotificationIOS.a is there)

enter image description here enter image description here

Step 3 : Augment AppDelegate

Step 3.1 : Update AppDelegate.h

At the top of the file add the following :

#import <UserNotifications/UNUserNotificationCenter.h>

Then, add the 'UNUserNotificationCenterDelegate' to protocols as shown below :

@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>

Step 3.2 : Update AppDelegate.m

At the top of the file add the following :

#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>

Replace all entries in your AppDelegate.m for RCTPushNotificationManager with RNCPushNotificationIOS

Then, add the following code snippet just before @end as per react-native-community.push-notification-ios

// Required to register for notifications
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
  [RNCPushNotificationIOS didRegisterUserNotificationSettings:notificationSettings];
}
// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
  [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
  [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
  [RNCPushNotificationIOS didReceiveLocalNotification:notification];
}

Other helpful Tips!

whenever you update your package.json, do the following :

rm -rf -rf node_modules
yarn cache clean --force
yarn install
cd ios && pod install
React-native start -- --reset-cache

Hope this helps someone!