Matthias M.
Matthias M.

Reputation: 41

Broken autobinding in arrow function for referenced node modules when using react-native with react-relay

I'm using react-native and react-relay, therefore I've the following .babelrc file:

{
  "sourceMaps": "both",
  "presets": [
    "./plugins/babelRelayPlugin",
    "react-native"
  ],
  "passPerPreset": true
}

Adding a dependency which uses arrow functions in their components as the MKIconToggle from react-native-material-kit (https://github.com/xinthink/react-native-material-kit) doesn't get transpiled correctly and the this reference is lost/wrong.

The original code which ultimately causes the error looks like the following:

_onLayout = (evt) => {
    this._onLayoutChange(evt.nativeEvent.layout);

    if (this.props.onLayout) {
      this.props.onLayout(evt);
    }
  };

The affected code fragment in the error case:

d(55, function(global, require, module, exports) {var _this = this,
    _jsxFileName = '.../node_modules/react-native-material-kit/lib/mdl/Ripple.js';
var Ripple = function (_Component) {
  babelHelpers.inherits(Ripple, _Component);

  function Ripple(props) {
    babelHelpers.classCallCheck(this, Ripple);

    var _this2 = babelHelpers.possibleConstructorReturn(this, Object.getPrototypeOf(Ripple).call(this, props));

    _this2._onLayout = function (evt) {
      _this._onLayoutChange(evt.nativeEvent.layout);

      if (_this.props.onLayout) {
        _this.props.onLayout(evt);
      }
    };

The _this reference equals window, due to the usage of _this the _this2 is created and used but _this is still used in the arrow functions(_onLayout)

When I delete the babelrc file and the default runs I get the following transpiled JS and it works:

__d(921, function(global, require, module, exports) {var jsxFileName='...../node_modules/react-native-material-kit/lib/mdl/Ripple.js';

Component=React.Component;var Animated=React.Animated;var View=React.View;var PropTypes=React.PropTypes;var Platform=React.Platform;var Ripple=function(_Component){
babelHelpers.inherits(Ripple,_Component);
function Ripple(props){babelHelpers.classCallCheck(this,Ripple);
var _this=babelHelpers.possibleConstructorReturn(this,Object.getPrototypeOf(Ripple).call(this, props));
_this._onLayout=function(evt){
_this._onLayoutChange(evt.nativeEvent.layout);

if(_this.props.onLayout){
_this.props.onLayout(evt);}};_this.

I'm not really certain what causes the issue, I can fix it by binding the function in the constructor but I'd rather not change code in dependencies directly. I've already tried to add various presets to the babel conf: es2015, stage-0, babel-preset-react-native-stage-0 and some others all without luck.

Funny thing is this behaviour doesn't occur in all dependencies and also not in my own code, if I just write a single component with an arrow function in it and use the babelrc it still works.

I'm not able to 100% reproduce this behaviour, I've seen it with other dependencies as well but it seems to come and go, although once it occurs it doesn't usually go away anymore.

Upvotes: 3

Views: 116

Answers (1)

Matthias M.
Matthias M.

Reputation: 41

babel-preset-react-native-stage-0 did it in the end. Not sure what was left in the cache or somewhere else but after clearing it all with: watchman watch-del-all rm -rf $TMPDIR/react-* rm -rf node_modules npm install npm start --reset-cache my project and all it's arrow functions work.

Upvotes: 0

Related Questions