Skip to content

Commit 24b7e26

Browse files
fixed an issue with update-react-imports codemod
1 parent e012f11 commit 24b7e26

12 files changed

Lines changed: 70 additions & 19 deletions

File tree

update-react-imports/scripts/codemod.ts

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,27 @@ const transform: Transform<TSX> = async (root) => {
7676
const isReactUsedAsValue = reactAsValue.length > 0;
7777

7878
if (isReactUsedAsValue) {
79-
const newImportText = `import * as ${reactName} from "react";`;
8079
const importStatement = reactDefaultImport.node.ancestors().find(
81-
(a) => a.kind() === "import_statement"
80+
(a) => a.kind() === "import_statement",
8281
);
8382
if (importStatement) {
84-
edits.push(importStatement.replace(newImportText));
83+
const source = importStatement.field("source");
84+
const sourceText = source?.text() ?? '"react"';
85+
const namedImports = importStatement.find({
86+
rule: { kind: "named_imports" },
87+
});
88+
const namespaceLine = `import * as ${reactName} from ${sourceText};`;
89+
if (namedImports) {
90+
const namedLine = `import ${namedImports.text()} from ${sourceText};`;
91+
edits.push(importStatement.replace(`${namespaceLine}\n${namedLine}`));
92+
} else {
93+
edits.push(importStatement.replace(namespaceLine));
94+
}
8595
}
8696

8797
transformMetric.increment({
8898
action: "convert-to-namespace",
8999
reason: "react-used-as-value",
90-
file: root.filename(),
91100
});
92101
} else if (reactMemberUsages.size > 0) {
93102
const namedImportsToAdd: string[] = [];
@@ -115,21 +124,40 @@ const transform: Transform<TSX> = async (root) => {
115124
transformMetric.increment({
116125
action: "convert-member-to-named",
117126
members: namedList,
118-
file: root.filename(),
119127
}, totalConversions);
120128
} else {
129+
const importStatement = reactDefaultImport.node.ancestors().find(
130+
(a) => a.kind() === "import_statement",
131+
);
132+
if (!importStatement) {
133+
return null;
134+
}
121135

122-
const removeEdit = removeImport(rootNode, {
123-
type: "default",
124-
from: "react",
136+
const namedImports = importStatement.find({
137+
rule: { kind: "named_imports" },
125138
});
126-
if (removeEdit) {
127-
edits.push(removeEdit);
139+
140+
if (namedImports) {
141+
const source = importStatement.field("source");
142+
const sourceText = source?.text() ?? '"react"';
143+
const newImportText = `import ${namedImports.text()} from ${sourceText};`;
144+
edits.push(importStatement.replace(newImportText));
128145
transformMetric.increment({
129146
action: "remove-default-import",
130147
reason: "only-jsx-usage",
131-
file: root.filename(),
132148
});
149+
} else {
150+
const removeEdit = removeImport(rootNode, {
151+
type: "default",
152+
from: "react",
153+
});
154+
if (removeEdit) {
155+
edits.push(removeEdit);
156+
transformMetric.increment({
157+
action: "remove-default-import",
158+
reason: "only-jsx-usage",
159+
});
160+
}
133161
}
134162
}
135163

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { useState } from "react";
2+
3+
export function Counter() {
4+
const [n, setN] = useState(0);
5+
return (
6+
<button type="button" onClick={() => setN(n + 1)}>
7+
{n}
8+
</button>
9+
);
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React, { useState } from "react";
2+
3+
export function Counter() {
4+
const [n, setN] = useState(0);
5+
return (
6+
<button type="button" onClick={() => setN(n + 1)}>
7+
{n}
8+
</button>
9+
);
10+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"react-import-updates": [
3+
{
4+
"cardinality": {
5+
"action": "remove-default-import",
6+
"reason": "only-jsx-usage"
7+
},
8+
"count": 1
9+
}
10+
]
11+
}

update-react-imports/tests/fragment-only/metrics.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
{
44
"cardinality": {
55
"action": "remove-default-import",
6-
"file": "tests/fragment-only/input.tsx",
76
"reason": "only-jsx-usage"
87
},
98
"count": 1

update-react-imports/tests/jsx-only/metrics.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
{
44
"cardinality": {
55
"action": "remove-default-import",
6-
"file": "tests/jsx-only/input.tsx",
76
"reason": "only-jsx-usage"
87
},
98
"count": 1

update-react-imports/tests/member-expression/metrics.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
{
44
"cardinality": {
55
"action": "convert-member-to-named",
6-
"file": "tests/member-expression/input.tsx",
76
"members": "createElement"
87
},
98
"count": 1

update-react-imports/tests/mixed-usage/metrics.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
{
44
"cardinality": {
55
"action": "convert-member-to-named",
6-
"file": "tests/mixed-usage/input.tsx",
76
"members": "Component, createElement"
87
},
98
"count": 2

update-react-imports/tests/original-react-basic-default-export/metrics.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
{
44
"cardinality": {
55
"action": "convert-member-to-named",
6-
"file": "tests/original-react-basic-default-export/input.tsx",
76
"members": "createElement"
87
},
98
"count": 1

update-react-imports/tests/original-react-not-removed/metrics.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
{
44
"cardinality": {
55
"action": "convert-to-namespace",
6-
"file": "tests/original-react-not-removed/input.tsx",
76
"reason": "react-used-as-value"
87
},
98
"count": 1

0 commit comments

Comments
 (0)