0

I am trying to set up expo-notifications on an existing react-native project that has recently been upgraded to expo 49.0.5. I have created a custom hook to handle all my notification logic.

However as soon as I run the app using the Expo Go app on my iPad, after it finishes compiling, I get the following error:

TypeError: Cannot read property 'custom' of undefined, js engine: hermes
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:105:15 in reportException
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:150:4 in handleException
at node_modules/react-native/Libraries/Core/setUpErrorHandling.js:26:18 in handleError
at node_modules/expo/build/errors/ExpoErrorManager.js:27:16 in errorHandler
at node_modules/expo/build/errors/ExpoErrorManager.js:32:8 in anonymous
at node_modules/@react-native/js-polyfills/error-guard.js:51:16 in reportFatalError
at node_modules/metro-runtime/src/polyfills/require.js:237:19 in guardedLoadModule
at http://192.168.1.246:19000/index.bundle?platform=ios&dev=true&hot=false&strict=false&minify=false:null in metroRequire
at http://192.168.1.246:19000/index.bundle?platform=ios&dev=true&hot=false&strict=false&minify=false:null in global 

I have been able narrow down the cause of the error is when I add this import statement import * as Notifications from "expo-notifications

So I decided to try creating a brand new expo app with the same dependencies, and that worked! But the problem is I need it on this existing project...

Here is the custom hook I am using:

import { useState, useEffect, useRef, useCallback } from "react";
//notifications
import * as Device from "expo-device";
import * as Notifications from "expo-notifications";
// init notification handler
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: false,
  }),
});
const useNotification = () => {
    const [notification, setNotification] = useState(false);
    const [expoPushToken, setExpoPushToken] = useState("");
    const notificationListener = useRef();
    const responseListener = useRef();
    useEffect(() => {
      registerForPushNotificationsAsync().then((token) => {
        console.log("token", token)
        alert(token);
        setExpoPushToken(token)
      });
      notificationListener.current =
        Notifications.addNotificationReceivedListener((notification) => {
          console.log("got a notificiation", notification)
          setNotification(notification);
        });
      responseListener.current =
        Notifications.addNotificationResponseReceivedListener((response) => {
          console.log(response);
        });
      return () => {
        Notifications.removeNotificationSubscription(
          notificationListener.current
        );
        Notifications.removeNotificationSubscription(responseListener.current);
      };
    }, []);
    return { expoPushToken, notification };
};
export default useNotification;
export async function schedulePushNotification() {
  await Notifications.scheduleNotificationAsync({
    content: {
      title: "You've got mail! ",
      body: "Here is the notification body",
      data: { data: "goes here" },
    },
    trigger: { seconds: 2 },
  });
}

async function registerForPushNotificationsAsync() {
  let token;
  if (Platform.OS === "android") {
    await Notifications.setNotificationChannelAsync("default", {
      name: "default",
      importance: Notifications.AndroidImportance.MAX,
      vibrationPattern: [0, 250, 250, 250],
      lightColor: "#FF231F7C",
    });
  }
  if (Device.isDevice) {
    const { status: existingStatus } =
      await Notifications.getPermissionsAsync();
    let finalStatus = existingStatus;
    if (existingStatus !== "granted") {
      const { status } = await Notifications.requestPermissionsAsync();
      finalStatus = status;
    }
    if (finalStatus !== "granted") {
      alert("Failed to get push token for push notification!");
      return;
    }
    token = (await Notifications.getExpoPushTokenAsync()).data;
    console.log(token);
  } else {
    alert("Must use physical device for Push Notifications");
  }
  return token;
}

Here is my package.json

{
  "scripts": {
    "start": "expo start --dev-client",
    "android": "expo run:android",
    "ios": "expo run:ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "@expo/config-plugins": "~7.2.2",
    "@gorhom/bottom-sheet": "^4",
    "@react-native-async-storage/async-storage": "1.18.2",
    "@react-native-community/netinfo": "9.3.10",
    "@react-native-masked-view/masked-view": "0.2.9",
    "@react-navigation/native": "^6.0.11",
    "@react-navigation/native-stack": "^6.2.5",
    "@sentry/react-native": "5.5.0",
    "@tanstack/query-sync-storage-persister": "^4.0.10",
    "@tanstack/react-query": "^4.0.10",
    "@tanstack/react-query-persist-client": "^4.0.10",
    "aws-amplify": "^4.3.22",
    "axios": "^0.24.0",
    "dayjs": "^1.10.7",
    "expo": "^49.0.5",
    "expo-app-auth": "~11.1.0",
    "expo-application": "~5.3.0",
    "expo-auth-session": "~5.0.2",
    "expo-blur": "~12.4.1",
    "expo-checkbox": "~2.4.0",
    "expo-clipboard": "~4.3.0",
    "expo-constants": "~14.4.2",
    "expo-device": "~5.4.0",
    "expo-document-picker": "~11.5.4",
    "expo-file-system": "~15.4.2",
    "expo-font": "~11.4.0",
    "expo-image-manipulator": "~11.3.0",
    "expo-image-picker": "~14.3.2",
    "expo-linear-gradient": "~12.3.0",
    "expo-location": "~16.1.0",
    "expo-media-library": "~15.4.1",
    "expo-notifications": "~0.18.1",
    "expo-random": "~13.2.0",
    "expo-screen-orientation": "~6.0.4",
    "expo-secure-store": "~12.3.1",
    "expo-splash-screen": "~0.20.4",
    "expo-status-bar": "~1.6.0",
    "expo-updates": "~0.18.11",
    "expo-web-browser": "~12.3.2",
    "jwt-decode": "^3.1.2",
    "moment": "^2.29.1",
    "msal": "^1.4.14",
    "react": "18.2.0",
    "react-aad-msal": "^2.3.5",
    "react-dom": "18.2.0",
    "react-hook-form": "^7.34.2",
    "react-native": "0.72.3",
    "react-native-aws3": "0.0.9",
    "react-native-calendar-strip": "^2.2.5",
    "react-native-calendars": "^1.1269.0",
    "react-native-compressor": "^1.1.1",
    "react-native-dotenv": "^3.4.9",
    "react-native-dropdown-picker": "^5.2.3",
    "react-native-geocoding": "^0.5.0",
    "react-native-gesture-handler": "~2.12.0",
    "react-native-google-places-autocomplete": "^2.4.1",
    "react-native-keyboard-aware-scroll-view": "^0.9.5",
    "react-native-maps": "1.7.1",
    "react-native-progress": "^5.0.0",
    "react-native-radial-gradient": "^1.0.9",
    "react-native-reanimated": "~3.3.0",
    "react-native-safe-area-context": "4.6.3",
    "react-native-screens": "~3.22.0",
    "react-native-select-dropdown": "^2.0.4",
    "react-native-svg": "13.9.0",
    "react-native-svg-transformer": "^0.14.3",
    "react-native-url-polyfill": "^1.3.0",
    "react-native-virtualized-view": "^1.0.0",
    "react-native-web": "~0.19.6",
    "react-native-webview": "13.2.2",
    "sentry-expo": "~7.0.0",
    "shortid": "^2.2.16",
    "use-debounce": "^9.0.3",
    "xmldom": "^0.6.0"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "babel-plugin-module-resolver": "^4.1.0"
  },
  "private": true,
  "name": "salesappv2",
  "version": "1.0.0",
  "resolutions": {
    "@expo/config-plugins": "^5.0.0"
  }
}

And finally, here is my app.json

{
  "expo": {
    "name": "Momentum Sales 2.0 (MVP)",
    "slug": "MomentumSales",
    "scheme": "msauth.com.momentum.salesmvp",
    "version": "11.3.4",
    "icon": "./assets/icon.png",
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "cover",
      "backgroundColor": "#ffffff"
    },
    "updates": {
      "fallbackToCacheTimeout": 0,
      "url": "https://u.expo.dev"
    },
    "plugins": [
      [
        "expo-image-picker",
        {
          "photosPermission": "The app accesses your photos to let you upload documents.",
          "cameraPermission": "This app accesses your camera to let you upload documents."
        }
      ],
      [
        "expo-screen-orientation",
        {
          "initialOrientation": "PORTRAIT_UP"
        }
      ],
      "sentry-expo"
    ],
    "hooks": {
      "postPublish": [
        {
          "file": "sentry-expo/upload-sourcemaps",
          "config": {
            "organization": "momentum-solar-bx",
            "project": "sales-app"
          }
        }
      ]
    },
    "assetBundlePatterns": ["**/*"],
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "com.momentum.salesmvp",
      "infoPlist": {
        "UISupportedInterfaceOrientations": [
          "UIInterfaceOrientationLandscapeRight",
          "UIInterfaceOrientationLandscapeLeft",
          "UIInterfaceOrientationPortrait"
        ],
        "UISupportedInterfaceOrientations~ipad": [
          "UIInterfaceOrientationLandscapeRight",
          "UIInterfaceOrientationLandscapeLeft",
          "UIDeviceOrientationPortrait",
          "UIDeviceOrientationPortraitUpsideDown"
        ]
      }
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#FFFFFF"
      },
      "permissions": ["android.permission.RECORD_AUDIO"],
      "package": "com.momentum.salesmvp"
    },
    "web": {
      "favicon": "./assets/favicon.png"
    },
    "packagerOpts": {
      "config": "metro.config.js",
      "sourceExts": ["js", "jsx", "ts", "tsx", "svg"]
    },
    "runtimeVersion": {
      "policy": "sdkVersion"
    },
    "extra": {
    }
  }
}

If anyone could point me in the right direction here I would appreciate it so much!

What I have tried:

  • I have tried deleting my package-lock.json file and reinstalling node modules.

  • I have tried running expo-doctor --fix

  • I have tried to run the app through Expo Go on my iPhone instead of the iPad.

  • I also tried moving the import statement import * as Notifications from "expo-notifications directly into the App.js file to verify that it is indeed causing the crash.

  • I tried upgrading expo notifications to version 20, and downgrading to version 18.

  • Finally I created a brand new expo app and installed the same versions and dependencies. And it works perfectly on my iPhone and iPad through Expo Go. I just don't understand why it's not working on the existing project.

0 Answers0