diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-constant/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-constant/actual.js
new file mode 100644
index 000000000000..a6c1f9b6ec88
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-constant/actual.js
@@ -0,0 +1,4 @@
+function render() {
+ this.component = "div";
+ return () => ;
+}
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-constant/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-constant/expected.js
new file mode 100644
index 000000000000..aa7a9994baeb
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-constant/expected.js
@@ -0,0 +1,7 @@
+function render() {
+ this.component = "div";
+
+ var _ref = ;
+
+ return () => _ref;
+}
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/actual.js
new file mode 100644
index 000000000000..bdc61d684a69
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/actual.js
@@ -0,0 +1,5 @@
+class Component extends React.Component {
+ subComponent = () => Sub Component
+
+ render = () =>
+}
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/expected.js
new file mode 100644
index 000000000000..9ce3a08e7437
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/expected.js
@@ -0,0 +1,12 @@
+var _ref = Sub Component;
+
+class Component extends React.Component {
+ constructor(...args) {
+ var _temp;
+
+ var _ref2 = ;
+
+ return _temp = super(...args), this.subComponent = () => _ref, this.render = () => _ref2, _temp;
+ }
+
+}
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/options.json b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/options.json
new file mode 100644
index 000000000000..d4789bbda3fb
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/options.json
@@ -0,0 +1,3 @@
+{
+ "plugins": ["syntax-jsx", "transform-react-constant-elements", "transform-class-properties"]
+}
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/actual.js
new file mode 100644
index 000000000000..2ab59df97b89
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/actual.js
@@ -0,0 +1,6 @@
+const els = {
+ subComponent: () => Sub Component
+};
+class Component extends React.Component {
+ render = () =>
+}
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/expected.js
new file mode 100644
index 000000000000..fe12eb988d5d
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/expected.js
@@ -0,0 +1,16 @@
+var _ref = Sub Component;
+
+const els = {
+ subComponent: () => _ref
+};
+
+var _ref2 = ;
+
+class Component extends React.Component {
+ constructor(...args) {
+ var _temp;
+
+ return _temp = super(...args), this.render = () => _ref2, _temp;
+ }
+
+}
diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/options.json b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/options.json
new file mode 100644
index 000000000000..d4789bbda3fb
--- /dev/null
+++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/options.json
@@ -0,0 +1,3 @@
+{
+ "plugins": ["syntax-jsx", "transform-react-constant-elements", "transform-class-properties"]
+}
diff --git a/packages/babel-traverse/src/path/lib/hoister.js b/packages/babel-traverse/src/path/lib/hoister.js
index 8a36031f1e79..3e992e4408cf 100644
--- a/packages/babel-traverse/src/path/lib/hoister.js
+++ b/packages/babel-traverse/src/path/lib/hoister.js
@@ -2,11 +2,23 @@ import { react } from "babel-types";
import * as t from "babel-types";
const referenceVisitor = {
+ // This visitor looks for bindings to establish a topmost scope for hoisting.
ReferencedIdentifier(path, state) {
- if (path.isJSXIdentifier() && react.isCompatTag(path.node.name)) {
+ // Don't hoist regular JSX identifiers ('div', 'span', etc).
+ // We do have to consider member expressions for hoisting (e.g. `this.component`)
+ if (path.isJSXIdentifier() && react.isCompatTag(path.node.name) && !path.parentPath.isJSXMemberExpression()) {
return;
}
+ // If the identifier refers to `this`, we need to break on the closest non-arrow scope.
+ if (path.node.name === "this") {
+ let scope = path.scope;
+ do {
+ if (scope.path.isFunction() && !scope.path.isArrowFunctionExpression()) break;
+ } while (scope = scope.parent);
+ if (scope) state.breakOnScopePaths.push(scope.path);
+ }
+
// direct references that we need to track to hoist this to the highest scope we can
const binding = path.scope.getBinding(path.node.name);
if (!binding) return;