expo: Native module cannot be null

Summary

bare workflow in ios not able to use InAppPurchases in ios tried every version of unimodule

“react-native-unimodules”: “^0.11.0”,

if I comment below line in expo-in-app-purchase->build->InAppPurchases.js // const eventEmitter = new EventEmitter(ExpoInAppPurchases); then it will work

Managed or bare workflow? If you have ios/ or android/ directories in your project, the answer is bare!

bare

What platform(s) does this occur on?

iOS

SDK Version (managed workflow only)

No response

Environment

“react”: “16.13.1”, “react-native”: “^0.63.2”,

ejected bare flow

Reproducible demo or steps to reproduce from a blank project https://github.com/dhairyasenjaliya/InAppPurchaseTest

No response

simulator_screenshot_AB4AC6F6-15A6-42E7-8BDE-4608D80EDFD7

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 37 (8 by maintainers)

Most upvoted comments

@cruzach would you consider re-opening this? Prior to SDK 40, we were able to run our app within Expo Go. Understandably, we can’t test in-app-purchases in Expo Go, but we could use Expo Go for all other portions, and then switch to XCode only for testing purchases. As of SDK 40, we can no longer use Expo Go at all due to the error mentioned (which is a big hit to productivity).

Using the repro that @brg8 put together, if you switch to using expo v39, the app runs fine, but using SDK 40 (and also 41) it blows up with the mentioned error. https://github.com/brg8/expo-in-app-purchases-violation-repro/tree/main

It’s quite unfortunate, that a simple import statements breaks DX in such a way. I’ve managed to use lukewis try/catch approach and also stubbed all functions my code uses

let InAppPurchases = {
  connectAsync: () => new Promise<void>(resolve => resolve()),
  disconnectAsync: () => new Promise<void>(resolve => resolve()),
  getProductsAsync: () => new Promise(resolve => resolve({ responseCode: 2, results: [] })),
  ...
};

try {
  InAppPurchases = require("expo-in-app-purchases");
} catch {
  console.warn(
    "Unable to load expo-in-app-purchases.  This is expected if running in Expo Go."
  );
}

This way TS is happy and I don’t have to mess with my implementation code.

If there’s no way to not break DX so badly, I would suggest to put the types in a dedicated package maybe? 🤔

Anyhow. It seems my Expo Go days are over and I now have to use Xcode 😃

@picklenick-dev I was never able to fully resolve this, and still wish this issue would be reopened. However, i was finally able to get the optional imports approach working. Toughest part was tracking down all the areas that import this module and updating them to be optional. Using this approach, I’m now able to show a sensible warning when running in expo go saying that iap is not supported in expo go. As stated originally, it’s disappointing that this behavior changed recently and now requires the optional import method to avoid crashing. Still feels like a regression issue to me.

Thanks for the tip @cruzach! Unfortunately I’m still having trouble. I’m using SDK 41 and have my import as follows:

let InAppPurchases: any;
try {
  InAppPurchases = require("expo-in-app-purchases");
} catch {
  console.warn(
    "Unable to load expo-in-app-purchases.  This is expected if running in Expo Go."
  );
}

But I still see the same error. The only way I’ve been able to run is by commenting out the line that @picklenick-dev mentions above (which is much appreciated, but doesn’t feel like a sustainable solution). Besides SDK 40, are there any other necessary dependencies (specific react/react-native versions, etc)? I’m currently using

"expo": "^41.0.0",
"expo-in-app-purchases": "~10.1.1",
"react": "16.13.1",
"react-native": "0.63.4",

Yup. I had the same problem. It worked by commenting out that line.

Try all those steps I wrote in my earlier comment.

I would also recommend creating a new project with expo init, add expo-in-app-purchase and then do expo eject.

Compare your AppDelegate and every file and see if there is a difference. After you’ve done that do a new pod install.

I spent a few days on this…