facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
118.17k stars 24.21k forks source link

classProperties isn't currenty enabled #21075

Closed vitorcamachoo closed 5 years ago

vitorcamachoo commented 6 years ago

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$"
    ],
hramos commented 6 years ago

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

Aidurber commented 6 years ago

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

hramos commented 6 years ago

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

oneroman commented 6 years ago

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

ide commented 6 years ago

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.

barbsicle commented 6 years ago

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.

oneroman commented 6 years ago

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 "babel-core@7.0.0-bridge.0"
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#babel-core@6.26.3"
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#babel-core@6.26.3"
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#babel-core@6.26.3"
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#babel-core@6.26.3"
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#babel-core@6.26.3"
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#babel-core@6.26.3"
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.
vadimkorr commented 5 years ago

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

vitorcamachoo commented 5 years ago

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 :
```json
  "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"
  }
FrederickEngelhardt commented 5 years ago

πŸ‘ Ran into this issue today.

nickmarca commented 5 years ago

@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.

corpsemxq commented 5 years ago

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

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

BodhiHu commented 5 years ago

could try the official babel-upgrade

allmaxgit commented 5 years ago

Continues in React native 0.57.5.

fwal commented 5 years ago

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 react-native@0.57.1

nonewcode commented 5 years ago

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"
  }
}
mattvick commented 5 years ago

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"]
}
kelset commented 5 years ago

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

ComicScrip commented 5 years ago

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 :)

bj97301 commented 5 years ago

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.

wuweijian1997 commented 4 years ago

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