Skip to content

tylergaw/RNUpgradePath

Repository files navigation

Upgrading or Creating a New React Native Project with 0.57.x Build Status

Posted 2018-11-16

Updated 2018-11-19

Between RN 0.54.x and 0.57.x lots of things changed that make the upgrade and even new project creation path a bit rough. I first tried to upgrade a project from 0.54 and hit a wall. Then I tried to create a new project with react-native init and hit a few of the same issues. These are steps I took along the path to get a working React Native project using 0.57.5.

NOTE: The final source code may not exactly match the examples below. I added more as I worked, you should be able to go back through the commits to get to any of the states though.

Issues

  1. Couldn't find preset "module:metro-react-native-babel-preset"
  2. "Jest encountered an unexpected token" (static properties)
  3. Unable to resolve module regenerator-runtime/runtime
  4. Cannot read property 'default' of undefined

Steps:

  1. Update to latest react-native-cli globally
# react-native -v
react-native-cli: 2.0.1
react-native: 0.57.5
  1. Create a new project
react-native init UpgradeTest
  1. Add some "stuff"

In my original project I hit a wall trying to run tests with Jest. So that's a focus for this upgrade project. I wanted to get similar components in place and be able to test them with yarn test or npm test. I created one Button component that lives in a components directory.

Screenshot of the components directory

Button.js is a basic TouchableOpacity element. With stuff in place, time to test.

yarn test

Issue 1:

# yarn test
yarn run v1.12.3
$ jest
 FAIL  components/__tests__/Button.test.js
  ● Test suite failed to run

    Couldn't find preset "module:metro-react-native-babel-preset" relative to directory "/Users/tyler/Desktop/UpgradeTest"

      at node_modules/babel-core/lib/transformation/file/options/option-manager.js:293:19
          at Array.map (<anonymous>)
      at OptionManager.resolvePresets (node_modules/babel-core/lib/transformation/file/options/option-manager.js:275:20)
      at OptionManager.mergePresets (node_modules/babel-core/lib/transformation/file/options/option-manager.js:264:10)
      at OptionManager.mergeOptions (node_modules/babel-core/lib/transformation/file/options/option-manager.js:249:14)
      at OptionManager.init (node_modules/babel-core/lib/transformation/file/options/option-manager.js:368:12)
      at File.initOptions (node_modules/babel-core/lib/transformation/file/index.js:212:65)
      at new File (node_modules/babel-core/lib/transformation/file/index.js:135:24)
      at Pipeline.transform (node_modules/babel-core/lib/transformation/pipeline.js:46:16)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.466s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

This seems to be a common problem with both upgrading existing projects and creating new projects.

In this Github issue comment it's suggested we rename .babelrc to babel.config.js. That worked for me.

With that I changed, again try to run tests

yarn test

Issue 2:

# yarn test
yarn run v1.12.3
$ jest
 FAIL  components/__tests__/Button.test.js
  ● Test suite failed to run

    /Users/tyler/Desktop/UpgradeTest/node_modules/react-native/jest/mockComponent.js: Unexpected token (20:23)

      Jest encountered an unexpected token
      This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
      By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
      Here's what you can do:
       • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
       • If you need a custom transformation specify a "transform" option in your config.
       • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
      You'll find more details and examples of these config options in the docs:
      https://jestjs.io/docs/en/configuration.html
      Details:
        18 |
        19 |   const Component = class extends SuperClass {
      > 20 |     static displayName = 'Component';
           |                        ^
        21 |
        22 |     render() {
        23 |       const name =

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.429s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

The error message here is not so helpful, but issue seems to be static class properties. This took a good bit of searching to find and it seems like it's pretty widespread. This comment has a fix that worked for me.

On that advice, I added the transform key to my jest config in package.json:

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

Once again yarn test. This time all tests pass as expected.

# yarn test
yarn run v1.12.3
$ jest
 PASS  components/__tests__/Button.test.js
  Button
    ✓ renders correctly with props (279ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   1 passed, 1 total
Time:        0.95s, estimated 5s
Ran all test suites.
✨  Done in 1.65s.

Issue 3:

Note: This didn't happen in this project, but did in another RN project that I was upgrading from RN 0.54.x.

When attempting to start the Metro bundler with yarn start, I got:

Error: Unable to resolve module `regenerator-runtime/runtime` from `/Users/gcred/workspace/streetcred/app/node_modules/react-native/Libraries/Core/InitializeCore.js`: Module `regenerator-runtime/runtime` does not exist in the Haste module map

This might be related to https://github.com/facebook/react-native/issues/4968

To resolve try the following:
  1. Clear watchman watches: `watchman watch-del-all`.
  2. Delete the `node_modules` folder: `rm -rf node_modules && npm install`.
  3. Reset Metro Bundler cache: `rm -rf /tmp/metro-bundler-cache-*` or `npm start -- --reset-cache`.
  4. Remove haste cache: `rm -rf /tmp/haste-map-react-native-packager-*`.

I followed those four steps, but the problem persisted. I took a look in my local node_modules folder and noticed there was not a regenerator-runtime directory. When running npm ls I also noticed a few other warnings about missing peer dependencies. With that, I guessed that my yarn.lock and/or package-lock.json files were stale, so I:

  1. Deleted yarn.lock and package-lock.json
  2. rm -rf node_modules
  3. yarn && npm i

That reinstalled the dependencies and regenerated the lock files. After that, yarn start works as normal.

Issue 4:

Any code with class properties–including class methods bound with fat arrows (these get compiled to class props)–will cause Jest tests to fail.

In the example, I've updated the App component to include one of these methods.

class App extends PureComponent {
  doWork = () => {
    console.log("This doesn't do anything. Writing this function to make sure fat arrow class methods work. Narrator: They don't work");
  }

  render() {
    return <Home />;
  }
}

The app still runs in the simulator but, tests now fail:

# yarn test
yarn run v1.12.3
$ jest
 FAIL  __tests__/App.test.js
  ● Console

    console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8060
      The above error occurred in the <App> component:
          in App (at App.test.js:7)

      Consider adding an error boundary to your tree to customize error handling behavior.
      Visit https://fb.me/react-error-boundaries to learn more about error boundaries.

  ● App › renders correctly

    TypeError: Cannot read property 'default' of undefined

      2 | import { Home } from "Screens";
      3 |
    > 4 | class App extends PureComponent {
        |                                                                          ^
      5 |   doWork = () => {
      6 |     console.log("This doesn't do anything. Writing this function to make sure fat arrow class methods work.")
      7 |   }

      at new App (App.js:4:383)
      at constructClassInstance (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4810:18)
      at updateClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6579:5)
      at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7413:16)
      at performUnitOfWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:10138:12)
      at workLoop (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:10170:24)
      at renderRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:10256:7)
      at performWorkOnRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11121:7)
      at performWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11033:7)
      at performSyncWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11007:3)

 PASS  components/Screens/__tests__/Home.test.js
 PASS  components/Patterns/__tests__/Button.test.js

Test Suites: 1 failed, 2 passed, 3 total
Tests:       1 failed, 2 passed, 3 total
Snapshots:   2 passed, 2 total
Time:        1.216s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

This seems to be a somewhat common issue, but it took days to track down something that worked for me. In this comment the person mentioned they removed inlineRequires from the jest preprocessor. That finally fixed this for me and in this example project.

In this project-and another production project–I make a copy of the preprocessor and save it in the root directory as jest.preprocessor.js. Comment out the inlineRequires: true option. Then update the transform setting in package.json to point to the local preprocessor:

...
"transform": {
  "^.+\\.js$": "<rootDir>/jest.preprocessor.js"
}
...

About

An example repo for getting RN 0.57.x working

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published