0

I thought I would post my experience facing a rare but hard-to-debug react native class-transformer issue.

Much has already been said about how to use set up class-transformer in react-native, a much-needed library if we are to deal conveniently with complex types like unserialised javascript Dates being returned from an API. Long story short, you need to set an array of niche babel plugins to get those decorators to work, my set-up in the babel.config.js file is the following:

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
    [
      'module:react-native-dotenv',
      {
        moduleName: '@env',
        allowUndefined: true,
      },
    ],
    'react-native-reanimated/plugin',
    'babel-plugin-transform-typescript-metadata',
    '@babel/plugin-transform-flow-strip-types',
    ['@babel/plugin-proposal-decorators', {legacy: true}],
  ],
};

Everything was working well until I tried to use class-transformer to type my JSON object stored in Async Storage (to create state persistence between usages) when I got this issue: Screenshot of Error

And on the console:

 ERROR  TypeError: undefined is not a function, js engine: hermes
 LOG  Running "App" with {"rootTag":251,"initialProps":{}}
 ERROR  Invariant Violation: "App" 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.registerComponent` wasn't called., js engine: hermes

2 Answers2

0

The fact that it is creating an Invariant Violation means in react-native terms that this issue is occurring before render and therefore is not an issue with the usage but rather with compiling.

One would have thought that all the ts configs and babel presets would be fine given that it is working and compiling correctly elsewhere, but that only applies to code within react-native functions, and the initialisation of my global context was outside of the App function (the highest function just below index.js) like so:

export const GlobalContext = React.createContext<GlobalContextInterface | null>({state: initialState, dispatch: () => null});

I initialise it with these empty values to avoid having to deal with possibly null values (as I know that the first line in my App function is going to set my context to the useReducer state and dispatch values so it will never actually be null).

My mistake however was in the way I was going about this dummy initialisation. setting state to {} would have been enough but instead I was creating an empty object of type State. Since this object was created outside of the react native functions it was not picked up by babel decorator plugins and wasn't compiling properly.

0

I fix this issue, importing in my entrypoint file reflect-metadata

Install this package https://www.npmjs.com/package/reflect-metadata and import

import 'reflect-metadata';
buster95
  • 640
  • 7
  • 7