Skip to content

Variable assignment while object destructuring not working properly 'Error: "action" is read-only.' #10193

@pwnreza

Description

@pwnreza

Bug Report

Current Behavior
We have a promise rejection in our react-native app.
It is possible to log it thru logcat (android logs).
It is regarding following code: See Input Code

When I try to "overload" the 'someAction' variable I get an runtime error which I can inspect via logcat (android logs used on my react-native app) looking something like this:

Possible Unhandled Promise Rejection (id: 1): Error: "someAction" is read-only.

If I don't "overload" the variable and instead try to do something like this
componentWillMount() { this.props.someAction(); }
it will work.

I guess it has something to do with how the babel helper handles the arguments and/or the export/imports.
But I am not sure at all.

Input Code

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { someAction } from '../../store/data/actions';

class SomeComponent extends Component {
  componentWillMount() {
    this.foo();
  }

  async foo() {
    const { someAction } = this.props;
    return await someAction();
  }

  render() {
    return null;
  }
}

export default connect(null, {
  someAction,
})(SomeComponent);

Expected behavior/code
Expected behavior would be that I can use a variable name inside my class/component (i.e. getting my action out of my props attribute by destructuring), even tho the variable name is also taken by the import of the action in the file.

Babel Configuration (.babelrc, package.json, cli command)

{
  "presets": ["module:metro-react-native-babel-preset"],
  "env": {
    "production": {
      "plugins": ["transform-remove-console"]
    }
  }
}

    "@babel/runtime": "^7.5.4",
    "babel-plugin-transform-remove-console": "^6.9.4",
    "metro-react-native-babel-preset": "^0.55.0",

Environment

  • Babel version(s): 7.5.4
  • Node/npm version: Node v10.15.3 / Npm 6.4.1
  • OS: OSX 10.14.5
  • How you are using Babel: react-native

Additional context/Screenshots
Babel transpiles the code to something like this:

__d(function(global, _$$_REQUIRE, _$$_IMPORT_DEFAULT, _$$_IMPORT_ALL, module, exports, _dependencyMap) {
    var _interopRequireDefault = _$$_REQUIRE(_dependencyMap[0], "@babel/runtime/helpers/interopRequireDefault");
    var _interopRequireWildcard = _$$_REQUIRE(_dependencyMap[1], "@babel/runtime/helpers/interopRequireWildcard");
    Object.defineProperty(exports, "__esModule", {
        value: true
    });
    exports.default = void 0;
    var _regenerator = _interopRequireDefault(_$$_REQUIRE(_dependencyMap[2], "@babel/runtime/regenerator"));
    var _classCallCheck2 = _interopRequireDefault(_$$_REQUIRE(_dependencyMap[3], "@babel/runtime/helpers/classCallCheck"));
    var _createClass2 = _interopRequireDefault(_$$_REQUIRE(_dependencyMap[4], "@babel/runtime/helpers/createClass"));
    var _possibleConstructorReturn2 = _interopRequireDefault(_$$_REQUIRE(_dependencyMap[5], "@babel/runtime/helpers/possibleConstructorReturn"));
    var _getPrototypeOf2 = _interopRequireDefault(_$$_REQUIRE(_dependencyMap[6], "@babel/runtime/helpers/getPrototypeOf"));
    var _inherits2 = _interopRequireDefault(_$$_REQUIRE(_dependencyMap[7], "@babel/runtime/helpers/inherits"));
    var _react = _interopRequireWildcard(_$$_REQUIRE(_dependencyMap[8], "react"));
    var _index = _interopRequireDefault(_$$_REQUIRE(_dependencyMap[9], "./../../../node_modules/react-transform-hmr/lib/index.js"));
    var _reactRedux = _$$_REQUIRE(_dependencyMap[10], "react-redux");
    var _actions = _$$_REQUIRE(_dependencyMap[12], "../../store/data/actions");
    var _services = _$$_REQUIRE(_dependencyMap[15], "../../services");
    var _jsxFileName = "/somePath/node_modules/react-native/app/components/SomeComponent/SomeComponent.js";
    var _components = {
        SomeComponent: {
            displayName: "SomeComponent"
        }
    };
    var _node_modulesReactTransformHmrLibIndexJs2 = (0, _index.default)({
        filename: "/somePath/node_modules/react-native/app/components/SomeComponent/SomeComponent.js",
        components: _components,
        locals: [module],
        imports: [_react.default]
    });

    function _wrapComponent(id) {
        return function(Component) {
            return _node_modulesReactTransformHmrLibIndexJs2(Component, id);
        };
    }
    var SomeComponent = function(_Component) {
        (0, _inherits2.default)(SomeComponent, _Component);

        function SomeComponent() {
            (0, _classCallCheck2.default)(this, SomeComponent);
            return (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(SomeComponent).apply(this, arguments));
        }(0, _createClass2.default)(SomeComponent, [{
            key: "componentWillMount",
            value: function componentWillMount() {
                this.foo();
            }
        }, {
            key: "foo",
            value: function foo() {
                var _this$props, someAction, _ref, type;
                return _regenerator.default.async(function foo$(_context) {
                    while (1) {
                        switch (_context.prev = _context.next) {
                            case 0:
                                _this$props = this.props, _actions.someAction = (_this$props.someAction, function() {
                                    throw new Error('"' + "someAction" + '" is read-only.');
                                }());
                                return _regenerator.default.awrap((0, _actions.someAction)());
                            case "end":
                                return _context.stop();
                        }
                    }
                }, null, this);
            }
        }, {
            key: "render",
            value: function render() {
                return null;
            }
        }]);
        return SomeComponent;
    }(_react.Component);
    SomeComponent = _wrapComponent("SomeComponent")(SomeComponent);
    var _default2 = (0, _reactRedux.connect)(null, {
        someAction: _actions.someAction,
    })(SomeComponent);
    exports.default = _default2;
}, 1365, [1, 544, 208, 114, 115, 122, 123, 125, 137, 255, 539, 575, 581, 956, 543, 584], "app/components/SomeComponent/SomeComponent.js");

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions