React-native: classProperties isn't currenty enabled

Created on 12 Sep 2018  ·  21Comments  ·  Source: facebook/react-native

Environment

Run react-native info in your terminal and paste its contents here.

React Native Environment Info:
    System:
      OS: macOS High Sierra 10.13.6
      CPU: x64 Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
      Memory: 88.00 MB / 8.00 GB
      Shell: 5.3 - /bin/zsh
    Binaries:
      Node: 9.10.0 - ~/.nvm/versions/node/v9.10.0/bin/node
      Yarn: 1.7.0 - /usr/local/bin/yarn
      npm: 5.6.0 - ~/.nvm/versions/node/v9.10.0/bin/npm
      Watchman: 4.9.0 - /usr/local/bin/watchman
    SDKs:
      iOS SDK:
        Platforms: iOS 11.4, macOS 10.13, tvOS 11.4, watchOS 4.3
      Android SDK:
        Build Tools: 23.0.1, 23.0.2, 23.0.3, 24.0.3, 25.0.0, 25.0.3, 26.0.2, 27.0.0, 27.0.1, 27.0.3
        API Levels: 23, 24, 25, 27
    IDEs:
      Android Studio: 3.1 AI-173.4819257
      Xcode: 9.4.1/9F2000 - /usr/bin/xcodebuild
    npmPackages:
      react: 16.5.0 => 16.5.0
      react-native: 0.57.0 => 0.57.0

Description

After update to latest react-native version (0.57.0), every test that I run, throws the same error related with some missing plugin (@babel/plugin-proposal-properties)

● Test suite failed to run

    SyntaxError: /Users/vitorcamacho/workspace/mbanka-earth/node_modules/react-native/jest/mockComponent.js: Support for the experimental syntax 'classProperties' isn't currently enabled (20:24):

      18 |
      19 |   const Component = class extends SuperClass {
    > 20 |     static displayName = 'Component';
         |                        ^
      21 |
      22 |     render() {
      23 |       const name =

    Add @babel/plugin-proposal-class-properties (https://git.io/vb4SL) to the 'plugins' section of your Babel config to enable transformation.

      at Parser.raise (node_modules/@babel/parser/lib/index.js:3938:15)
      at Parser.expectPlugin (node_modules/@babel/parser/lib/index.js:5252:18)
      at Parser.parseClassProperty (node_modules/@babel/parser/lib/index.js:8102:12)
      at Parser.pushClassProperty (node_modules/@babel/parser/lib/index.js:8066:30)
      at Parser.parseClassMemberWithIsStatic (node_modules/@babel/parser/lib/index.js:7999:14)
      at Parser.parseClassMember (node_modules/@babel/parser/lib/index.js:7936:10)
      at Parser.parseClassBody (node_modules/@babel/parser/lib/index.js:7891:12)
      at Parser.parseClass (node_modules/@babel/parser/lib/index.js:7841:10)
      at Parser.parseExprAtom (node_modules/@babel/parser/lib/index.js:6304:21)
      at Parser.parseExprSubscripts (node_modules/@babel/parser/lib/index.js:5923:21)

and my jest configuration is:

// package.json
"jest": {
    "preset": "react-native",
    "setupFiles": [
      "./jest.setup.js"
    ],
    "transformIgnorePatterns": [
      "node_modules/(?!react-native|react-navigation|victory|rn-placeholder|redux-persist).+\\.js$"
    ],
Bug Locked 📦Bundler

Most helpful comment

Changing the config inside package.json will solve the issue. I think this has also been written earlier. The transform is all you need to add to get around this for now.

"jest": {
  "preset": "react-native",
  "transform": {
    "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
  }
}

All 21 comments

Do you have any babel dependencies that are not yet using v7.0.0?

@hramos Is there a yarn/npm command to determine that? I have quite a few dependencies.

I was referring to any Babel dependencies in your own package.json, as recommended in the upgrade guidelines at https://github.com/react-native-community/react-native-releases/blob/master/CHANGELOG.md#updating-to-this-version

For instance metro has babel-preset-fbjs as dependency which uses many babel plugins ver. 6. Could it be related this issue?

You can run yarn why babel-core (for example) to have Yarn print out the physical dependency trace with versions. The Yarn lockfile also contains this information since it references the precise version numbers.

Something tells me that this comment still holds weight - following step 3 lets my tests run again.

However, tests which require a mocked child component with relative imports fail as they still bring in the original component. Unfortunately I have no idea how to get around it.

Test File example:

jest.mock('../global/ChildComponent', () => 'ChildComponent');
import ChildComponent from '../global/ChildComponent';

import { ParentComponent } from './ParentComponent';

...

// standard render tests here

Jest Output:

Invariant Violation: Could not find "store" in either the context or props of "Connect(ChildComponent)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(ChildComponent)".

Jest Config:

"jest": {
  "preset": "react-native",
  "transform": {
    "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
  },
  "setupFiles": [
    "<rootDir>/src/setupTests.js"
  ],
  "coveragePathIgnorePatterns": [
    "/node_modules/",
    "/src/setupTests.js"
  ]
}

Hope this helps the investigation and gives people a workaround for now.

even metro and fbjs-scripts uses babel ver.6. This is my config:

[1/4] 🤔  Why do we have the module "babel-core"...?
[2/4] 🚚  Initialising dependency graph...
[3/4] 🔍  Finding dependency...
[4/4] 🚡  Calculating file sizes...
=> Found "[email protected]"
info Has been hoisted to "babel-core"
info This module exists because it's specified in "devDependencies".
info Disk size without dependencies: "12MB"
info Disk size with unique dependencies: "12MB"
info Disk size with transitive dependencies: "12MB"
info Number of shared dependencies: 0
=> Found "metro#[email protected]"
info This module exists because "react-native#metro" depends on it.
info Disk size without dependencies: "212MB"
info Disk size with unique dependencies: "6.39GB"
info Disk size with transitive dependencies: "13.2GB"
info Number of shared dependencies: 44
=> Found "fbjs-scripts#[email protected]"
info This module exists because "react-native#fbjs-scripts" depends on it.
info Disk size without dependencies: "176MB"
info Disk size with unique dependencies: "6.36GB"
info Disk size with transitive dependencies: "13.16GB"
info Number of shared dependencies: 44
=> Found "jest-config#[email protected]"
info This module exists because "jest#jest-cli#jest-config" depends on it.
info Disk size without dependencies: "176MB"
info Disk size with unique dependencies: "6.36GB"
info Disk size with transitive dependencies: "13.16GB"
info Number of shared dependencies: 44
=> Found "jest-runtime#[email protected]"
info This module exists because "jest#jest-cli#jest-runtime" depends on it.
info Disk size without dependencies: "176MB"
info Disk size with unique dependencies: "6.36GB"
info Disk size with transitive dependencies: "13.16GB"
info Number of shared dependencies: 44
=> Found "babel-register#[email protected]"
info This module exists because "react-native#metro#babel-register" depends on it.
info Disk size without dependencies: "176MB"
info Disk size with unique dependencies: "6.36GB"
info Disk size with transitive dependencies: "13.16GB"
info Number of shared dependencies: 44
=> Found "babel-plugin-emotion#[email protected]"
info This module exists because "react-native#metro#metro-visualizer#emotion#babel-plugin-emotion" depends on it.
info Disk size without dependencies: "196MB"
info Disk size with unique dependencies: "6.38GB"
info Disk size with transitive dependencies: "13.18GB"
info Number of shared dependencies: 44
✨  Done in 2.11s.

In my case, I solved the issue by the following:
It seems that my .babelrc was ignored, so created babel.config.js with identical configs and it solved initial issue:

// babel.config.js
module.exports = {
  plugins: [
    ['@babel/plugin-proposal-decorators', { legacy: true }],
    ['@babel/plugin-proposal-class-properties', { loose: true }],
    '@babel/plugin-syntax-dynamic-import',
    '@babel/plugin-transform-regenerator',
    [
      '@babel/plugin-transform-runtime',
      {
        helpers: false,
        regenerator: true,
      },
    ],
  ],
  presets: [
    '@babel/preset-env',
    'module:metro-react-native-babel-preset',
    '@babel/preset-react',
    '@babel/typescript',
  ],
};

Then it caused new issue (because my component is using Button component)

TypeError: Cannot read property 'bind' of undefined
at new bind (node_modules/react-native/Libraries/Animated/src/createAnimatedComponent.js:39:53)

console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:5190
    The above error occurred in the <AnimatedComponent> component:
        in AnimatedComponent (created by TouchableOpacity)
        in TouchableOpacity (created by Button)
        in Button (created by Home)
        in View (created by Component)
        in Component (created by Home)
        in Home

It was solved by adding @babel/plugin-transform-flow-strip-types before @babel/plugin-proposal-class-properties (details are here https://github.com/facebook/react-native/issues/20150#issuecomment-417858270) :

module.exports = {
  plugins: [
    '@babel/plugin-transform-flow-strip-types',
    // ...
  ]
]

That's it.

By the way, versions I'm using, and some sources:
"react-native": "^0.57.0",
"jest": "^23.6.0",
"ts-jest": "^23.1.4",

// jest.config.js
module.exports = {
  preset: 'react-native',
  roots: ['<rootDir>'],
  transform: {
    '^.+\\.tsx$': 'babel-jest',
  },
  testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  globals: {
    'ts-jest': {
      tsConfigFile: 'tsconfig.jest.json',
    },
  },
  modulePaths: ['<rootDir>'],
};

Hope it'll help

I end up doing this to make it work on testing and on running the app on Android and iOS:

  1. Deprecate .babelrc in favor of babel.config.js with the following content:
module.exports = (api) => {
  api.cache(true)

  return {
    presets: ['module:metro-react-native-babel-preset'],
    plugins: [
      '@babel/plugin-transform-runtime',
      '@babel/plugin-proposal-class-properties',
    ].map(require.resolve),
  }
}

and my jest config is :

  "jest": {
    "preset": "react-native",
    "setupFiles": [
      "./jest.setup.js"
    ],
    "modulePathIgnorePatterns": [
      "e2e"
    ],
    "testMatch": [
      "<rootDir>/src/**/*.spec.js"
    ],
    "transformIgnorePatterns": [
      "node_modules/(?!react-|victory|rn-placeholder|redux-persist).+\\.js$"
    ],
    "testResultsProcessor": "<rootDir>/node_modules/jest-html-reporter",
    "coverageDirectory": "<rootDir>/reporters/coverage"
  }

👍 Ran into this issue today.

@vitorcamachoo 's answer worked for me. I'm on RN 0.57.3, generated by react-native init. It looks like the new version of react-native-cli is ignoring .babelrc.

'@babel/plugin-transform-flow-strip-types',

Thank you so much @vadimkorr. You saved my life......

could try the official babel-upgrade

Continues in React native 0.57.5.

Can confirm that adding @babel/plugin-proposal-class-properties to plugins list in babel config works, but only when using babel.config.js.

Using .babelrc or a babel key in package.json _did not work_.

Tested with [email protected]

Changing the config inside package.json will solve the issue. I think this has also been written earlier. The transform is all you need to add to get around this for now.

"jest": {
  "preset": "react-native",
  "transform": {
    "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
  }
}

I had a similar issue and solved this by deleting the .babelrc file:

// .babelrc
{
  "presets": ["module:metro-react-native-babel-preset"]
}

Then adding a babel.config.js file:

// babel.config.js
module.exports = {
  presets: ["module:metro-react-native-babel-preset"]
}

I feel that we can close this, since it seems like it was related to an old configuration/babel issue.

Yep, still not working for me..
When I yarn test, I've got :

[...]node_modules/react-native/jest/mockComponent.js:20
        static displayName = 'Component';
                           ^
    SyntaxError: Unexpected token =

here's my package.json :

{
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "start-rc": "node node_modules/react-native/local-cli/cli.js start --reset-cache",
    "test": "jest",
    "typecheck": "tsc --noEmit -p . --pretty",
    "transpile": "tsc -p . --pretty",
    "format": "npm-run-all format:*",
    "format:js": "prettier --write {.,**}/*.js",
    "format:json": "prettier --write {.,**}/*.json",
    "format:md": "prettier --write {.,**}/*.md",
    "format:ts": "prettier --write {.,**}/*.{ts,tsx} && tslint --fix -p .",
    "lint": "npm-run-all lint:*",
    "lint:ts": "tslint -p .",
    "postinstall": "solidarity",
    "preversion": "react-native-version --never-amend",
    "hack:types-react-navigation": "rimraf node_modules/@types/react-navigation/node_modules/@types",
    "hack:types-react-native": "rimraf node_modules/@types/react-native/node_modules/@types",
    "hack:types-react-test-renderer": "rimraf node_modules/@types/react-test-renderer/node_modules/@types",
    "patch": "patch-package",
    "prepare": "npm-run-all patch hack:*",
    "ios:deploy-beta": "fastlane ios deploy_beta",
    "ios:build": "fastlane ios build",
    "android:run-storybook": "react-native run-android && adb reverse tcp:9090 tcp:9090 && adb reverse tcp:3000 tcp:3000 && adb reverse tcp:9001 tcp:9001",
    "android:run-debug": "react-native run-android && adb reverse tcp:9090 tcp:9090 && adb reverse tcp:3000 tcp:3000",
    "android:deploy-beta": "fastlane android deploy_beta",
    "android:build": "fastlane android build",
    "android:install-build": "adb install android/app/build/outputs/apk/release/app-release.apk",
    "android:build-and-run": "ENVFILE=.env.beta yarn android:build && yarn android:install-build"
  },
  "dependencies": {
    "@babel/plugin-proposal-class-properties": "^7.4.0",
    "@babel/plugin-syntax-dynamic-import": "^7.2.0",
    "@types/chroma-js": "^1.4.1",
    "@types/react-native-material-kit": "^0.5.3",
    "@types/react-native-material-textfield": "^0.12.2",
    "apisauce": "^1.0.2",
    "chroma-js": "^2.0.3",
    "i18n-js": "^3.0.11",
    "lodash": "^4.17.11",
    "mobx": "^4.9.2",
    "mobx-logger": "^0.7.1",
    "mobx-persist": "^0.4.1",
    "mobx-react": "^5.4.3",
    "mobx-react-form": "^1.39.1",
    "mobx-utils": "5.2.0",
    "moment": "^2.24.0",
    "react": "^16.8.1",
    "react-native": "0.57.8",
    "react-native-config": "^0.11.7",
    "react-native-gesture-handler": "^1.0.10",
    "react-native-languages": "^3.0.0",
    "react-native-material-kit": "^0.5.1",
    "react-native-material-textfield": "^0.12.0",
    "react-native-modal-datetime-picker": "^6.1.0",
    "react-native-open-maps": "^0.3.3",
    "react-native-paper": "^2.11.0",
    "react-native-phone-call": "^1.0.9",
    "react-native-picker-select": "^6.1.0",
    "react-native-size-matters": "^0.1.6",
    "react-native-splash-screen": "3.1.1",
    "react-native-tab-view": "^1.3.2",
    "react-native-vector-icons": "^6.2.0",
    "react-navigation": "^3.2.1",
    "react-powerplug": "^1.0.0",
    "reactive-records": "^0.1.13"
  },
  "devDependencies": {
    "@babel/core": "^7.4.0",
    "@babel/plugin-proposal-decorators": "^7.0.0",
    "@babel/plugin-proposal-optional-catch-binding": "^7.0.0",
    "@babel/preset-env": "^7.4.2",
    "@babel/preset-typescript": "^7.3.3",
    "@babel/runtime": "^7.0.0",
    "@types/i18n-js": "^3.0.1",
    "@types/jest": "23.3.2",
    "@types/lodash": "^4.14.121",
    "@types/react": "16.7.7",
    "@types/react-native": "0.57.13",
    "@types/react-native-tab-view": "^1.0.4",
    "@types/react-navigation": "2.13.5",
    "@types/react-test-renderer": "16.0.3",
    "babel-jest": "^24.5.0",
    "husky": "^1.3.1",
    "jest": "^24.5.0",
    "metro-react-native-babel-preset": "0.51.1",
    "npm-run-all": "4.1.5",
    "patch-package": "5.1.1",
    "postinstall-prepare": "1.0.1",
    "prettier": "1.12.1",
    "react-devtools-core": "3.4.3",
    "react-dom": "16.5.0",
    "react-native-version": "^2.6.7",
    "react-test-renderer": "16.6.3",
    "rimraf": "2.6.2",
    "solidarity": "2.1.0",
    "ts-jest": "^24.0.0",
    "tslint": "5.11.0",
    "tslint-config-prettier": "1.15.0",
    "typescript": "3.0.3"
  },
  "husky": {
    "hooks": {
      "pre-commit": "yarn lint && yarn typecheck",
      "pre-push": ""
    }
  },
  "jest": {
    "preset": "react-native",
    "testURL": "http://localhost/",
    "transform": {
      "^.+\\.(js|jsx|ts|tsx)$": "./test/transform.js"
    },
    "testRegex": "/.*\\.spec\\.(ts|js)$",
    "transformIgnorePatterns": ["node_modules/(?!(react-native-size-matters)/)"],
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "jsx",
      "json",
      "node"
    ],
    "collectCoverage": false,
    "coverageReporters": [
      "json",
      "json-summary",
      "lcov",
      "text-summary",
      "html"
    ],
    "collectCoverageFrom": [
      "src/**/*.ts"
    ],
    "coverageDirectory": "test/coverage",
    "setupFilesAfterEnv": [
      "<rootDir>test/setup.ts"
    ]
  },
  "rnpm": {
    "assets": [
      "./app/assets/fonts/"
    ]
  }
}

transform.js

const config = require("../babel.config.js")
module.exports = require("babel-jest").createTransformer(config)

And my babel.config.json :

module.exports = {
  presets: [
    ['@babel/preset-env', {targets: {node: 'current'}}],
    '@babel/preset-typescript',
    "module:metro-react-native-babel-preset",
  ],
  "plugins": [
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    [
      "@babel/plugin-proposal-optional-catch-binding"
    ],
    [
      "@babel/plugin-syntax-dynamic-import"
    ],
    [
      "@babel/plugin-proposal-class-properties",
      { "loose": true }
    ]
  ]
};

I would like to transpile my code with Babel instead of ts-jest because I want to be able to run tests even with type-related errors.
What is wrong with my config ?
It's been 3 hours trying to get jest to run my test...

EDIT :

finally got this working by specifying

    "transformIgnorePatterns": ["node_modules/(?!(react-native|react-native-size-matters|react-native-vector-icons|react-native-material-textfield|react-native-languages|react-native-open-maps|react-native-tab-view|react-native-modal-datetime-picker|react-native-modal|react-native-animatable|react-navigation-stack|react-native-screens|react-native-gesture-handler|NativeModules|@react-navigation|react-native-phone-call|react-navigation-tabs)/)"]

in package.json

and in test/setup.ts :

// we always make sure 'react-native' gets included first
import 'react-native'
import { NativeModules as RNNativeModules } from 'react-native'
RNNativeModules.UIManager = RNNativeModules.UIManager || {}
RNNativeModules.UIManager.RCTView = RNNativeModules.UIManager.RCTView || {}
RNNativeModules.RNGestureHandlerModule = RNNativeModules.RNGestureHandlerModule || {
  State: { BEGAN: 'BEGAN', FAILED: 'FAILED', ACTIVE: 'ACTIVE', END: 'END' },
}

declare global {
  var __TEST__
}

// We need to mock native modules because they dont all export JS when published...

jest.mock('react-native-config', () => {
  return {}
})

jest.mock('react-native-languages', () => ({
  RNLanguages: {
    language: 'fr',
    languages: ['fr'],
  },
}))

jest.mock('NativeModules', () => ({
  UIManager: {
    RCTView: () => ({
      directEventTypes: {}
    })
  },
  PlatformConstants: {},
  KeyboardObserver: {},
  RNGestureHandlerModule: {
    attachGestureHandler: jest.fn(),
    createGestureHandler: jest.fn(),
    dropGestureHandler: jest.fn(),
    updateGestureHandler: jest.fn(),
    State: {},
    Directions: {}
  }
}))

Hope this can help someone :)

Changing the config inside package.json will solve the issue. I think this has also been written earlier. The transform is all you need to add to get around this for now.

"jest": {
  "preset": "react-native",
  "transform": {
    "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
  }
}

@joshuakelly been trying to fix this for hours. Thank you soooooooo much for sharing your fix.

I had a similar issue and solved this by deleting the .babelrc file:

// .babelrc
{
  "presets": ["module:metro-react-native-babel-preset"]
}

Then adding a babel.config.js file:

// babel.config.js
module.exports = {
  presets: ["module:metro-react-native-babel-preset"]
}

thx

Was this page helpful?
0 / 5 - 0 ratings