React-native: "babelHelpers.asyncToGenerator is not a function" on React-Native 0.16.0 and 0.17.0

Created on 17 Dec 2015  ·  33Comments  ·  Source: facebook/react-native

Hello,

I updated React-Native from 0.14.0 to 0.16.0 and from now, I have errors at runtime:

screen shot 2015-12-17 at 16 10 03

screen shot 2015-12-17 at 16 32 05

Here are the npm dependencies:

"dependencies": {
  "async": "^1.5.0",
  "immutable": "^3.7.6",
  "react-native": "^0.16.0",
  "react-native-contacts": "../../react-native-contacts",
  "react-native-contacts-rx": "^1.0.1",
  "react-native-gifted-messenger": "0.0.7",
  "react-native-i18n": "0.0.6",
  "react-redux": "^4.0.1",
  "redux": "^3.0.5",
  "rx": "^4.0.7"
},
"devDependencies": {
  "babel-eslint": "^5.0.0-beta6",
  "eslint": "^1.10.3",
  "eslint-config-airbnb": "^2.1.1",
  "eslint-plugin-react": "^3.11.3",
  "events": "^1.1.0",
  "flux": "^2.1.1",
  "keymirror": "^0.1.1",
  "lodash": "^3.10.1",
  "redux-devtools": "^3.0.0"
}

And my .babelrc file:

{
  "retainLines": true,
  "compact": true,
  "comments": false,
}

Any suggestions?

Locked

Most helpful comment

Hey ya'all...

Sorry for the lack of response on this issue. I want to explain a little bit about how the babel-preset works and why this error happens.

Babel is a complex beast. There are certain transforms that require "helpers" (contained in either babel-runtime, or included babelHelpers). React Native includes it's _own_ set of helpers, and it does this in order to improve startup performance (see the blog post that talks about it here: https://code.facebook.com/posts/895897210527114/dive-into-react-native-performance/ and the commit here: https://github.com/facebook/react-native/commit/b90fe8e2e8fd173498c268abf39a21b665e019ed). _Important takeway -- lacking certain babel helpers is not an issue, it's a feature :)_

This is perf impact is super important...but unfortunately, it makes the Babel setup a bit more complex than what you'd read in the Babel documentation where you can just throw

{ presets: ["es2015", "stage-0"] }

into your .babelrc and get the latest and greatest JS features. That's why we created the preset...it makes it easy for people to get started with a custom babelrc. Unfortunately, the stage-3 babel preset contains "async-to-generator", which transforms async function blah() into function* blah(). This is not necessary for react-native (and as you all have discovered, actually breaks), as it already includes transform-regenerator, which allows for consistent use of generators and async functions on the versions of JSC that react-native uses. It is the inclusion of that transform by the stage-3 preset (which the stage-0 and stage-1 presets transitively include) that causes this error when using babel-preset-react-native with babel-preset-stage-0 (or stage-1, stage-2 or stage-3).

In addition, it's important to note that babel-preset-react-native actually includes some stage-1 and stage-2 features. These are:

  • transform-class-properties
  • transform-object-rest-spread

However, being a group of developers who love to live on the cutting edge, we want to use all of the stage-0 features! A babelrc that would accomplish that goal would look like this:

{
  "presets": [ "react-native" ],
  "plugins": [ 
    "transform-do-expressions",
    "transform-function-bind",
    "transform-class-constructor-call",
    "transform-export-extensions",
    "syntax-trailing-function-commas",
    "transform-exponentiation-operator"
  ]
}

Note that it omits transform-async-to-generator as well as the two transforms from stage-1 and stage-2 that babel-preset-react-native already includes.

I've gone ahead and packaged this up into ANOTHER, unofficial babel-preset, called babel-preset-react-native-stage-0.

To use, simply npm install babel-preset-react-native-stage-0 --save and put

{ presets: ['react-native-stage-0'] }

in your .babelrc.

If you want experimental decorator support (provided by babel-plugin-transform-decorators-legacy), you can put:

{ presets: ['react-native-stage-0/decorator-support'] }

in your .babelrc instead.

Hope this helps everyone!

P.S.: Make sure when you change your babelrc, you clear watchman and packager caches for good measure:

watchman watch-del-all
[packager command] --reset-cache

All 33 comments

Hey JeanLebrument, thanks for reporting this issue!

React Native, as you've probably heard, is getting really popular and truth is we're getting a bit overwhelmed by the activity surrounding it. There are just too many issues for us to manage properly.

  • If you don't know how to do something or not sure whether some behavior is expected or a bug, please ask on StackOverflow with the tag react-native or for more real time interactions, ask on Discord in the #react-native channel.
  • If this is a feature request or a bug that you would like to be fixed, please report it on Product Pains. It has a ranking feature that lets us focus on the most important issues the community is experiencing.
  • We welcome clear issues and PRs that are ready for in-depth discussion. Please provide screenshots where appropriate and always mention the version of React Native you're using. Thank you for your contributions!

Try clearing the package cache may be?

rm -rf $TMPDIR/react*

+1 same issue here

rm -rf $TMPDIR/react* seems no use

@JeanLebrument i remove my own ./babelrc in root dir, then everything goes alright.

don't know why but works.

Thanks for your answer @filod but I need to use the preset stage-0 for my project.

@JeanLebrument All transforms in stage-0 are already enabled in React Native.

@satya164 - I don't think that is the case actually, it uses these plugins by default: https://github.com/facebook/react-native/blob/master/packager/react-packager/.babelrc

Your babelrc doesn't have any plugins or presets enabled, and babel6 doesn't enable any by default. You'll need to add those to your babelrc :)

@brentvatne Oh, I mistakenly said stage-0.

@brentvatne answer is out of date for anyone stumbling here: https://github.com/facebook/react-native/blob/e6cb02d61af82832016bafb259a1b0d3039a357e/babel-preset/README.md

babel-preset-react-native is the preferred way to integrate your own babelrc

Even with babel-preset-react-native I still get this error.

The same for me ! The following example doesn't work for me in React Native : https://goo.gl/0JEOwJ.
My babelrc :

{  "presets": ["react-native"] }

I remove my own babelrc in root dir, then everything goes alright ! But it seems impossible to use custom babelrc.

So, it appears that the RN packager has its own implementation of babelHelpers, which doesn't include an implementation for asyncToGenerator

@nevir - is there no way to use stage-0 async functions in react-native, then?

I'll leave the same comment here from: https://github.com/este/este/issues/662#issuecomment-189674310

It appears you can modify the react-native helpers file to (maybe?) fix this issue. Replace the helpers you find at /node_modules/react-native/packager/react-packager/src/Resolver/polyfills/babelHelpers.js (https://github.com/facebook/react-native/blob/master/packager/react-packager/src/Resolver/polyfills/babelHelpers.js) with the ones either generated yourself (how to: http://stackoverflow.com/questions/33703919/how-to-use-babel-6-external-helpers-in-the-browser) or from this code snippet:

  var babelHelpers = global.babelHelpers = {};
  babelHelpers.typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
    return typeof obj;
  } : function (obj) {
    return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;
  };

  babelHelpers.jsx = function () {
    var REACT_ELEMENT_TYPE = typeof Symbol === "function" && Symbol.for && Symbol.for("react.element") || 0xeac7;
    return function createRawReactElement(type, props, key, children) {
      var defaultProps = type && type.defaultProps;
      var childrenLength = arguments.length - 3;

      if (!props && childrenLength !== 0) {
        props = {};
      }

      if (props && defaultProps) {
        for (var propName in defaultProps) {
          if (props[propName] === void 0) {
            props[propName] = defaultProps[propName];
          }
        }
      } else if (!props) {
        props = defaultProps || {};
      }

      if (childrenLength === 1) {
        props.children = children;
      } else if (childrenLength > 1) {
        var childArray = Array(childrenLength);

        for (var i = 0; i < childrenLength; i++) {
          childArray[i] = arguments[i + 3];
        }

        props.children = childArray;
      }

      return {
        $$typeof: REACT_ELEMENT_TYPE,
        type: type,
        key: key === undefined ? null : '' + key,
        ref: null,
        props: props,
        _owner: null
      };
    };
  }();

  babelHelpers.asyncToGenerator = function (fn) {
    return function () {
      var gen = fn.apply(this, arguments);
      return new Promise(function (resolve, reject) {
        function step(key, arg) {
          try {
            var info = gen[key](arg);
            var value = info.value;
          } catch (error) {
            reject(error);
            return;
          }

          if (info.done) {
            resolve(value);
          } else {
            return Promise.resolve(value).then(function (value) {
              return step("next", value);
            }, function (err) {
              return step("throw", err);
            });
          }
        }

        return step("next");
      });
    };
  };

  babelHelpers.classCallCheck = function (instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  };

  babelHelpers.createClass = function () {
    function defineProperties(target, props) {
      for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
      }
    }

    return function (Constructor, protoProps, staticProps) {
      if (protoProps) defineProperties(Constructor.prototype, protoProps);
      if (staticProps) defineProperties(Constructor, staticProps);
      return Constructor;
    };
  }();

  babelHelpers.defineEnumerableProperties = function (obj, descs) {
    for (var key in descs) {
      var desc = descs[key];
      desc.configurable = desc.enumerable = true;
      if ("value" in desc) desc.writable = true;
      Object.defineProperty(obj, key, desc);
    }

    return obj;
  };

  babelHelpers.defaults = function (obj, defaults) {
    var keys = Object.getOwnPropertyNames(defaults);

    for (var i = 0; i < keys.length; i++) {
      var key = keys[i];
      var value = Object.getOwnPropertyDescriptor(defaults, key);

      if (value && value.configurable && obj[key] === undefined) {
        Object.defineProperty(obj, key, value);
      }
    }

    return obj;
  };

  babelHelpers.defineProperty = function (obj, key, value) {
    if (key in obj) {
      Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
      });
    } else {
      obj[key] = value;
    }

    return obj;
  };

  babelHelpers.extends = Object.assign || function (target) {
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i];

      for (var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
          target[key] = source[key];
        }
      }
    }

    return target;
  };

  babelHelpers.get = function get(object, property, receiver) {
    if (object === null) object = Function.prototype;
    var desc = Object.getOwnPropertyDescriptor(object, property);

    if (desc === undefined) {
      var parent = Object.getPrototypeOf(object);

      if (parent === null) {
        return undefined;
      } else {
        return get(parent, property, receiver);
      }
    } else if ("value" in desc) {
      return desc.value;
    } else {
      var getter = desc.get;

      if (getter === undefined) {
        return undefined;
      }

      return getter.call(receiver);
    }
  };

  babelHelpers.inherits = function (subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }

    subClass.prototype = Object.create(superClass && superClass.prototype, {
      constructor: {
        value: subClass,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
  };

  babelHelpers.instanceof = function (left, right) {
    if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
      return right[Symbol.hasInstance](left);
    } else {
      return left instanceof right;
    }
  };

  babelHelpers.interopRequireDefault = function (obj) {
    return obj && obj.__esModule ? obj : {
      default: obj
    };
  };

  babelHelpers.interopRequireWildcard = function (obj) {
    if (obj && obj.__esModule) {
      return obj;
    } else {
      var newObj = {};

      if (obj != null) {
        for (var key in obj) {
          if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];
        }
      }

      newObj.default = obj;
      return newObj;
    }
  };

  babelHelpers.newArrowCheck = function (innerThis, boundThis) {
    if (innerThis !== boundThis) {
      throw new TypeError("Cannot instantiate an arrow function");
    }
  };

  babelHelpers.objectDestructuringEmpty = function (obj) {
    if (obj == null) throw new TypeError("Cannot destructure undefined");
  };

  babelHelpers.objectWithoutProperties = function (obj, keys) {
    var target = {};

    for (var i in obj) {
      if (keys.indexOf(i) >= 0) continue;
      if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
      target[i] = obj[i];
    }

    return target;
  };

  babelHelpers.possibleConstructorReturn = function (self, call) {
    if (!self) {
      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }

    return call && (typeof call === "object" || typeof call === "function") ? call : self;
  };

  babelHelpers.selfGlobal = typeof global === "undefined" ? self : global;

  babelHelpers.set = function set(object, property, value, receiver) {
    var desc = Object.getOwnPropertyDescriptor(object, property);

    if (desc === undefined) {
      var parent = Object.getPrototypeOf(object);

      if (parent !== null) {
        set(parent, property, value, receiver);
      }
    } else if ("value" in desc && desc.writable) {
      desc.value = value;
    } else {
      var setter = desc.set;

      if (setter !== undefined) {
        setter.call(receiver, value);
      }
    }

    return value;
  };

  babelHelpers.slicedToArray = function () {
    function sliceIterator(arr, i) {
      var _arr = [];
      var _n = true;
      var _d = false;
      var _e = undefined;

      try {
        for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
          _arr.push(_s.value);

          if (i && _arr.length === i) break;
        }
      } catch (err) {
        _d = true;
        _e = err;
      } finally {
        try {
          if (!_n && _i["return"]) _i["return"]();
        } finally {
          if (_d) throw _e;
        }
      }

      return _arr;
    }

    return function (arr, i) {
      if (Array.isArray(arr)) {
        return arr;
      } else if (Symbol.iterator in Object(arr)) {
        return sliceIterator(arr, i);
      } else {
        throw new TypeError("Invalid attempt to destructure non-iterable instance");
      }
    };
  }();

  babelHelpers.slicedToArrayLoose = function (arr, i) {
    if (Array.isArray(arr)) {
      return arr;
    } else if (Symbol.iterator in Object(arr)) {
      var _arr = [];

      for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {
        _arr.push(_step.value);

        if (i && _arr.length === i) break;
      }

      return _arr;
    } else {
      throw new TypeError("Invalid attempt to destructure non-iterable instance");
    }
  };

  babelHelpers.taggedTemplateLiteral = function (strings, raw) {
    return Object.freeze(Object.defineProperties(strings, {
      raw: {
        value: Object.freeze(raw)
      }
    }));
  };

  babelHelpers.taggedTemplateLiteralLoose = function (strings, raw) {
    strings.raw = raw;
    return strings;
  };

  babelHelpers.temporalRef = function (val, name, undef) {
    if (val === undef) {
      throw new ReferenceError(name + " is not defined - temporal dead zone");
    } else {
      return val;
    }
  };

  babelHelpers.temporalUndefined = {};

  babelHelpers.toArray = function (arr) {
    return Array.isArray(arr) ? arr : Array.from(arr);
  };

  babelHelpers.toConsumableArray = function (arr) {
    if (Array.isArray(arr)) {
      for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];

      return arr2;
    } else {
      return Array.from(arr);
    }
  };

:+1: It worked for me but when this will be a permanent fix? Do we need to wait next version of react (i.e 0.21)?

Thanks,

@brentvatne can you investigate https://github.com/facebook/react-native/issues/4844#issuecomment-191282653 and https://github.com/facebook/react-native/issues/4844#issuecomment-190473078

Not sure if there is an issue or this belongs somewhere else, but it seems something is causing issues with the babel helpers.

Hey ya'all...

Sorry for the lack of response on this issue. I want to explain a little bit about how the babel-preset works and why this error happens.

Babel is a complex beast. There are certain transforms that require "helpers" (contained in either babel-runtime, or included babelHelpers). React Native includes it's _own_ set of helpers, and it does this in order to improve startup performance (see the blog post that talks about it here: https://code.facebook.com/posts/895897210527114/dive-into-react-native-performance/ and the commit here: https://github.com/facebook/react-native/commit/b90fe8e2e8fd173498c268abf39a21b665e019ed). _Important takeway -- lacking certain babel helpers is not an issue, it's a feature :)_

This is perf impact is super important...but unfortunately, it makes the Babel setup a bit more complex than what you'd read in the Babel documentation where you can just throw

{ presets: ["es2015", "stage-0"] }

into your .babelrc and get the latest and greatest JS features. That's why we created the preset...it makes it easy for people to get started with a custom babelrc. Unfortunately, the stage-3 babel preset contains "async-to-generator", which transforms async function blah() into function* blah(). This is not necessary for react-native (and as you all have discovered, actually breaks), as it already includes transform-regenerator, which allows for consistent use of generators and async functions on the versions of JSC that react-native uses. It is the inclusion of that transform by the stage-3 preset (which the stage-0 and stage-1 presets transitively include) that causes this error when using babel-preset-react-native with babel-preset-stage-0 (or stage-1, stage-2 or stage-3).

In addition, it's important to note that babel-preset-react-native actually includes some stage-1 and stage-2 features. These are:

  • transform-class-properties
  • transform-object-rest-spread

However, being a group of developers who love to live on the cutting edge, we want to use all of the stage-0 features! A babelrc that would accomplish that goal would look like this:

{
  "presets": [ "react-native" ],
  "plugins": [ 
    "transform-do-expressions",
    "transform-function-bind",
    "transform-class-constructor-call",
    "transform-export-extensions",
    "syntax-trailing-function-commas",
    "transform-exponentiation-operator"
  ]
}

Note that it omits transform-async-to-generator as well as the two transforms from stage-1 and stage-2 that babel-preset-react-native already includes.

I've gone ahead and packaged this up into ANOTHER, unofficial babel-preset, called babel-preset-react-native-stage-0.

To use, simply npm install babel-preset-react-native-stage-0 --save and put

{ presets: ['react-native-stage-0'] }

in your .babelrc.

If you want experimental decorator support (provided by babel-plugin-transform-decorators-legacy), you can put:

{ presets: ['react-native-stage-0/decorator-support'] }

in your .babelrc instead.

Hope this helps everyone!

P.S.: Make sure when you change your babelrc, you clear watchman and packager caches for good measure:

watchman watch-del-all
[packager command] --reset-cache

I got the same issue 'undefined is not a function (evaluating 'babelHelpers.asyncToGenerator') something doessnt compile without 'DEV' mode. but with the developer mode it doess'nt seem to have any issues. (Which makes debugging rather hard.)

EDIT: Appearantly its not yet included in react-native v0.26 without some adaptations to the .babelrc file:

Example:

npm install babel-preset-react-native-stage-0 --save

.babelrc

{
  "presets": ["react-native-stage-0"]
}

or with decorator support (not yet needed myself)

{
  "presets": ["react-native-stage-0/decorator-support"]
}

Empty cache and Restart

watchman watch-del-all
To ensure you have a new version of your application running on your phone:
./node_modules/react-native/packager/packager.sh start --reset-cache
Found and Thanks to Kyle Finley for the answer:
http://stackoverflow.com/questions/35563025/new-react-native-app-has-typeerror-babelhelpers-typeof-is-not-a-function-ios

Anyone knows how to get async generators/iterators working? I added plugin transform-async-generator-functions to .babelrc, but I'm getting Cannot read property 'wrap' of undefined when I try to use async generator function. More details here #10798.

rm -rf $TMPDIR/react*
this worked for me.

"clean": "rm -rf $TMPDIR/react-* && watchman watch-del-all && npm cache clean"

It worked for me, here is the link

None of the above worked for me, but it was an issue to do with something, somewhere in the cache. I resolved the issue by running

react-native start --reset-cache

I can't help but find the solutions posted here not really helpful
I agree that the answer of @skevy does a great deal of explanation and gives a great workaround for the stage-0-folks

If babel's mechanisms are broken on purpose to achieve better performance, fine - but I'd expect an alternative "react-native way of adding my own presets or plugins"

Right now, we are failing to get rid of the error described in #4831

I ran into this issue and the only way to solve it was to delete my .babelrc and run rm -rf $TMPDIR/react* && npm start --reset-cache.

RN 0.43.2

@liuliangsir I tried many ways, on the end, your suggestion solved my problem, Thanks

楼上竟然和我的偶像同名,还以为偶像也来写前端了

@jcollum Thanks! this solution work for me

@honeyjie please use english to comment, because this is a matter of basic politeness

@liuliangsir You are right, Thanks for your reminder

Nothing from here helped me so I made a workaround which seems to work with no problem:
npm i async-to-generator

Then, somewhere in your app:

import asyncToGenerator from 'async-to-generator'

babelHelpers.asyncToGenerator = asyncToGenerator

P.S.: what caused the problem was some library which I had installed. Changing .babelrc in that lib as described above also solved the problem

For me, When I remove "babel-preset-stage-0": "^6.24.1" from package.json and "state-0" from .babelrc. It works well

This happened to me in the released apk but not in the development environment. Any ideas?

Was this page helpful?
0 / 5 - 0 ratings