npm startでエラー 'React' must be in scope when using JSX

背景

Reactの本を買ったので、一年半ぶりにReactの記事を書きます。

書籍に書いてある通りcreate-react-appを実行して作成されたアプリケーションのディレクトリに移動します。

1
2
3
$ npx create-react-app my-react
$ cd my-react
$ npm start

すると、ブラウザに表示された画面は真っ白で、コンソールには

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> my-react@0.1.0 start
> react-scripts start
Starting the development server...
Failed to compile.

./src/App.js
Line 7:5: 'React' must be in scope when using JSX react/react-in-jsx-scope
Line 8:7: 'React' must be in scope when using JSX react/react-in-jsx-scope
Line 9:9: 'React' must be in scope when using JSX react/react-in-jsx-scope
Line 10:9: 'React' must be in scope when using JSX react/react-in-jsx-scope
Line 11:16: 'React' must be in scope when using JSX react/react-in-jsx-scope
Line 13:9: 'React' must be in scope when using JSX react/react-in-jsx-scope

Search for the keywords to learn more about each error.

と表示されてしまいました。

原因

調べてみると、src/App.jsの先頭行に以下の記述が必要だったようです。

1
import React from 'react';

一旦この行を追加してから実行してみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ npm start

> my-react@0.1.0 start
> react-scripts start
Starting the development server...
Compiled successfully!

You can now view my-react in the browser.

Local: http://localhost:3000/
On Your Network: http://192.168.11.7:3000/

Note that the development build is not optimized.
To create a production build, use npm run build.

確かに問題なく動作しました。
であれば、なぜその行の記述がなかったのでしょうか。

JSX Transform

React17から導入されたJSX Transfromでは、先ほど記述したimport文が不要になるというメリットがあるようです。
なにが変わったかというと、トランスパイル後のコードでReactを読み込まなくても動作するようになるということのようです。

では、なぜ、今回その行を追加しないとエラーになってしまったのでしょうか。

ESLint

調べてみるとESLintの設定でエラーを抑制するように書かれていました。
package.jsonを変更しながら、ruleの箇所を追加したり、extendsを変更したりしました。
しかし、結果的に修正できませんでした。

npm install react-scripts@latest

最後の方法として、react-scriptsを最新版にすることでした。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ npm install react-scripts@latest
npm WARN deprecated @babel/plugin-proposal-private-methods@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.
npm WARN deprecated @babel/plugin-proposal-numeric-separator@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.
npm WARN deprecated @babel/plugin-proposal-nullish-coalescing-operator@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.
npm WARN deprecated @babel/plugin-proposal-class-properties@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.
npm WARN deprecated rollup-plugin-terser@7.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
npm WARN deprecated @babel/plugin-proposal-optional-chaining@7.21.0: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.
npm WARN deprecated domexception@2.0.1: Use your platform's native DOMException instead
npm WARN deprecated sourcemap-codec@1.4.8: Please use @jridgewell/sourcemap-codec instead
npm WARN deprecated workbox-cacheable-response@6.6.0: workbox-background-sync@6.6.0

added 567 packages, removed 766 packages, changed 382 packages, and audited 1555 packages in 1m

254 packages are looking for funding
run `npm fund` for details

8 vulnerabilities (2 moderate, 6 high)

To address all issues (including breaking changes), run:
npm audit fix --force

Run `npm audit` for details.

deprecatedは一旦置いておいて、その後にnpm startします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ npm start

> my-react@0.1.0 start
> react-scripts start

(node:79721) [DEP_WEBPACK_DEV_SERVER_ON_AFTER_SETUP_MIDDLEWARE] DeprecationWarning: 'onAfterSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option.
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:79721) [DEP_WEBPACK_DEV_SERVER_ON_BEFORE_SETUP_MIDDLEWARE] DeprecationWarning: 'onBeforeSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option.
Starting the development server...
Compiled successfully!

You can now view my-react in the browser.

Local: http://localhost:3000
On Your Network: http://192.168.11.7:3000

Note that the development build is not optimized.
To create a production build, use npm run build.

webpack compiled successfully

無事動作しました。

何が変わったのか

何が変わったのかをみてみると、package.jsonの差分は1行だけでした。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ git diff package.json
diff --git a/package.json b/package.json
index 28afd0a..bd487ff 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
- "react-scripts": "5.0.1",
+ "react-scripts": "^5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {

package-lock.jsonをみると、結構変わっています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
$ git diff package-lock.json
diff --git a/package-lock.json b/package-lock.json
index ba7b477..f91a96e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,7 +13,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
- "react-scripts": "5.0.1",
+ "react-scripts": "^5.0.1",
"web-vitals": "^2.1.4"
}
},
@@ -257,9 +257,9 @@
}
},
"node_modules/@babel/helper-define-polyfill-provider": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz",
- "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==",
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz",
+ "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==",
"dependencies": {
"@babel/helper-compilation-targets": "^7.22.6",
"@babel/helper-plugin-utils": "^7.22.5",
@@ -3427,9 +3427,9 @@
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="
},
"node_modules/@rushstack/eslint-patch": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.6.1.tgz",
- "integrity": "sha512-UY+FGM/2jjMkzQLn8pxcHGMaVLh9aEitG3zY2CiY7XHdLiz3bZOwa6oDxNqEMv7zZkV+cj5DOdz0cQ1BP5Hjgw=="
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.7.0.tgz",
+ "integrity": "sha512-Jh4t/593gxs0lJZ/z3NnasKlplXT2f+4y/LZYuaKZW5KAaiVFL/fThhs+17EbUd53jUVJ0QudYCBGbN/psvaqg=="
},
"node_modules/@sinclair/typebox": {
"version": "0.24.51",
@@ -5359,9 +5359,9 @@
}
},
"node_modules/autoprefixer": {
- "version": "10.4.16",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz",
- "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSY
Jx5GKcpRCzBh7RH4/0dnY+uQ==",
+ "version": "10.4.17",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz",
+ "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3B
hA+nLo5tX8Cu0upUsGKvKbmg==",
"funding": [
{
"type": "opencollective",
@@ -5377,9 +5377,9 @@
}
],
"dependencies": {
- "browserslist": "^4.21.10",
- "caniuse-lite": "^1.0.30001538",
- "fraction.js": "^4.3.6",
+ "browserslist": "^4.22.2",
+ "caniuse-lite": "^1.0.30001578",
+ "fraction.js": "^4.3.7",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.0",
"postcss-value-parser": "^4.2.0"
@@ -5593,12 +5593,12 @@
}
},
"node_modules/babel-plugin-polyfill-corejs2": {
- "version": "0.4.7",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.7.tgz",
- "integrity": "sha512-LidDk/tEGDfuHW2DWh/Hgo4rmnw3cduK6ZkOI1NPFceSK3n/yAGeOsNT7FLnSGHkXj3RHGSEVkN3FsCTY6w2CQ==",
+ "version": "0.4.8",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz",
+ "integrity": "sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==",
"dependencies": {
"@babel/compat-data": "^7.22.6",
- "@babel/helper-define-polyfill-provider": "^0.4.4",
+ "@babel/helper-define-polyfill-provider": "^0.5.0",
"semver": "^6.3.1"
},
"peerDependencies": {
@@ -5625,12 +5625,27 @@
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
+ "node_modules/babel-plugin-polyfill-corejs3/node_modules/@babel/helper-define-polyfill-provider": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz",
+ "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==",
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.22.6",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "debug": "^4.1.1",
+ "lodash.debounce": "^4.0.8",
+ "resolve": "^1.14.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
"node_modules/babel-plugin-polyfill-regenerator": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.4.tgz",
- "integrity": "sha512-S/x2iOCvDaCASLYsOOgWOq4bCfKYVqvO/uxjkaYyZ3rVsVE3CeAI/c84NpyuBBymEgNvHgjEot3a9/Z/kXvqsg==",
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz",
+ "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==",
"dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.4.4"
+ "@babel/helper-define-polyfill-provider": "^0.5.0"
},
"peerDependencies": {
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
@@ -5965,9 +5980,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001576",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz",
- "integrity": "sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==",
+ "version": "1.0.30001579",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz",
+ "integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==",
"funding": [
{
"type": "opencollective",
@@ -8427,9 +8442,9 @@
"integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ=="
},
"node_modules/follow-redirects": {
- "version": "1.15.4",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
- "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
+ "version": "1.15.5",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
+ "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"funding": [
{
"type": "individual",
@@ -13960,9 +13975,9 @@
}
},
"node_modules/postcss-modules-local-by-default": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz",
- "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.4.tgz",
+ "integrity": "sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q==",
"dependencies": {
"icss-utils": "^5.0.0",
"postcss-selector-parser": "^6.0.2",
@@ -15407,12 +15422,12 @@
}
},
"node_modules/safe-array-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
- "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz",
+ "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==",
"dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.1",
+ "call-bind": "^1.0.5",
+ "get-intrinsic": "^1.2.2",
"has-symbols": "^1.0.3",
"isarray": "^2.0.5"
},
@@ -16611,9 +16626,9 @@
}
},
"node_modules/terser": {
- "version": "5.26.0",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz",
- "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==",
+ "version": "5.27.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz",
+ "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",

多すぎてどこが影響しているのかわかりません…

まとめ

ESLintの問題だと思って色々試していましたが、そうじゃなかったかもしれません。
まだ初心者なので、実際の原因はわかりませんが、こういう解決方法もあるのだということを学びました。

参考文献