[react-refresh/babel] Always insert registrations after var (#18794)
Previously, we transformed ``` let Foo = styled.div``; ``` to ``` let Foo = _c1 = styled.div``; ``` and then babel-plugin-styled-components would infer `_c1` as the display name. Widen the existing case that applies to function expressions to apply to any type of variable declaration.
Sophie Alpert committed
May 1, 2020 at 08:01 UTC
21670cf4be2da872bf0403aba060208b5ec357df
2 files changed
+32
-28
packages/react-refresh/src/ReactFreshBabelPlugin.js
+6
-7
@@ -689,16 +689,15 @@ export default function(babel, opts = {}) {
689
return;
690
}
691
const handle = createRegistration(programPath, persistentID);
692
- if (
693
- (targetExpr.type === 'ArrowFunctionExpression' ||
694
- targetExpr.type === 'FunctionExpression') &&
695
- targetPath.parent.type === 'VariableDeclarator'
696
- ) {
697
- // Special case when a function would get an inferred name:
692
+ if (targetPath.parent.type === 'VariableDeclarator') {
693
+ // Special case when a variable would get an inferred name:
694
// let Foo = () => {}
695
// let Foo = function() {}
696
+ // let Foo = styled.div``;
697
// We'll register it on next line so that
698
// we don't mess up the inferred 'Foo' function name.
699
+ // (eg: with @babel/plugin-transform-react-display-name or
700
+ // babel-plugin-styled-components)
701
insertAfterPath.insertAfter(
702
t.expressionStatement(
703
t.assignmentExpression('=', handle, declPath.node.id),
@@ -710,7 +709,7 @@ export default function(babel, opts = {}) {
709
targetPath.replaceWith(
710
t.assignmentExpression('=', handle, targetExpr),
711
);
713
- // Result: let Foo = _c1 = hoc(() => {})
712
+ // Result: let Foo = hoc(_c1 = () => {})
713
}
714
},
715
);
packages/react-refresh/src/__tests__/__snapshots__/ReactFreshBabelPlugin-test.js.snap
+26
-21
@@ -37,12 +37,12 @@ const Bar = () => {
37
_s4(Bar, "useContext{}");
38
39
_c2 = Bar;
40
-
41
-const Baz = _c4 = memo(_c3 = _s5(() => {
40
+const Baz = memo(_c3 = _s5(() => {
41
_s5();
42
43
return useContext(X);
44
}, "useContext{}"));
45
+_c4 = Baz;
46
47
const Qux = () => {
48
_s6();
@@ -108,20 +108,22 @@ exports[`ReactFreshBabelPlugin generates signatures for function expressions cal
108
var _s = $RefreshSig$(),
109
_s2 = $RefreshSig$();
110
111
-export const A = _c3 = React.memo(_c2 = React.forwardRef(_c = _s((props, ref) => {
111
+export const A = React.memo(_c2 = React.forwardRef(_c = _s((props, ref) => {
112
_s();
113
114
const [foo, setFoo] = useState(0);
115
React.useEffect(() => {});
116
return <h1 ref={ref}>{foo}</h1>;
117
}, "useState{[foo, setFoo](0)}\\nuseEffect{}")));
118
-export const B = _c6 = React.memo(_c5 = React.forwardRef(_c4 = _s2(function (props, ref) {
118
+_c3 = A;
119
+export const B = React.memo(_c5 = React.forwardRef(_c4 = _s2(function (props, ref) {
120
_s2();
121
122
const [foo, setFoo] = useState(0);
123
React.useEffect(() => {});
124
return <h1 ref={ref}>{foo}</h1>;
125
}, "useState{[foo, setFoo](0)}\\nuseEffect{}")));
126
+_c6 = B;
127
128
function hoc() {
129
var _s3 = $RefreshSig$();
@@ -326,9 +328,10 @@ function Foo() {
328
329
_c = Foo;
330
export default _c2 = hoc(Foo);
329
-export const A = _c3 = hoc(Foo);
330
-
331
-const B = _c4 = hoc(Foo);
331
+export const A = hoc(Foo);
332
+_c3 = A;
333
+const B = hoc(Foo);
334
+_c4 = B;
335
336
var _c, _c2, _c3, _c4;
337
@@ -342,7 +345,8 @@ exports[`ReactFreshBabelPlugin registers identifiers used in JSX at definition s
345
import A from './A';
346
import Store from './Store';
347
Store.subscribe();
345
-const Header = _c = styled.div\`color: red\`;
348
+const Header = styled.div\`color: red\`;
349
+_c = Header;
350
const Factory = funny.factory\`\`;
351
let Alias1 = A;
352
let Alias2 = A.Foo;
@@ -353,12 +357,12 @@ function Foo() {
357
}
358
359
_c2 = Foo;
360
+const B = hoc(A); // This is currently registered as a false positive:
361
357
-const B = _c3 = hoc(A); // This is currently registered as a false positive:
358
-
359
-
360
-const NotAComponent = _c4 = wow(A); // We could avoid it but it also doesn't hurt.
362
+_c3 = B;
363
+const NotAComponent = wow(A); // We could avoid it but it also doesn't hurt.
364
365
+_c4 = NotAComponent;
366
367
var _c, _c2, _c3, _c4;
368
@@ -372,7 +376,8 @@ exports[`ReactFreshBabelPlugin registers identifiers used in React.createElement
376
import A from './A';
377
import Store from './Store';
378
Store.subscribe();
375
-const Header = _c = styled.div\`color: red\`;
379
+const Header = styled.div\`color: red\`;
380
+_c = Header;
381
const Factory = funny.factory\`\`;
382
let Alias1 = A;
383
let Alias2 = A.Foo;
@@ -384,12 +389,12 @@ function Foo() {
389
390
_c2 = Foo;
391
React.createContext(Store);
392
+const B = hoc(A); // This is currently registered as a false positive:
393
388
-const B = _c3 = hoc(A); // This is currently registered as a false positive:
389
-
390
-
391
-const NotAComponent = _c4 = wow(A); // We could avoid it but it also doesn't hurt.
394
+_c3 = B;
395
+const NotAComponent = wow(A); // We could avoid it but it also doesn't hurt.
396
397
+_c4 = NotAComponent;
398
399
var _c, _c2, _c3, _c4;
400
@@ -400,14 +405,14 @@ $RefreshReg$(_c4, "NotAComponent");
405
`;
406
407
exports[`ReactFreshBabelPlugin registers likely HOCs with inline functions 1`] = `
403
-const A = _c2 = forwardRef(_c = function () {
408
+const A = forwardRef(_c = function () {
409
return <h1>Foo</h1>;
410
});
406
-
407
-const B = _c5 = memo(_c4 = React.forwardRef(_c3 = () => {
411
+_c2 = A;
412
+const B = memo(_c4 = React.forwardRef(_c3 = () => {
413
return <h1>Foo</h1>;
414
}));
410
-
415
+_c5 = B;
416
export default _c8 = React.memo(_c7 = forwardRef(_c6 = (props, ref) => {
417
return <h1>Foo</h1>;
418
}));