React の勉強するのに、コードフォーマットとかチェックとかは WebStorm に勝手にやってもらいたいなぁ

と思ったので、設定してみることにした。あんまり分かってない状態でやってる。自分用のメモ。

Prettier でコードフォーマットをして、 ESLint で解析するって感じなんだね。新旧情報があって混乱するけど↓ここ読んで雰囲気を整理した。もともとは ESLint のプラグインとして Prettier が動いてたのだけど、今はもう別々に動かすようになってるってことかー。

eslint-plugin-prettier を ESLint から 分離するサンプル – Intellij IDEA の設定変更も | DevelopersIO

それと、↓この記事も参考にしました!まだあんまり書いてることが理解できないので、この通りにやったわけじゃないけど、全部書き終わったあとに見てみたら少し分かるようになってて嬉しかった

React × Typescript × ESLint × Prettier × VSCodeなSetup - Qiita

今日のコードはここに置いといた

GitHub - bufferings/hello-eslint

Create React App

ということで、React のプロジェクトを作ってみる。この辺を読んで

TypeScript にしておきたいので --template typescript をつけて、あとで ESLint の --init で npm が使われるので、なんとなく Yarn じゃなくて npm にしておきたい気持ち。なので --use-npm にして、こうかな?

❯ npx create-react-app hello-eslint --template typescript --use-npm

これで hello-eslint ってフォルダの中にプロジェクトが作られる。

Vulnerability?

生成時にこういうメッセージが出てて

27 vulnerabilities (16 moderate, 9 high, 2 critical)

「そういうものなのかなぁ?」と思ってたら、↓書いてくれてる記事があった。気にしなくて良さそう。

create-react-appでは脆弱性の警告が出るが無視して良い

GitHub の Issue に書いてあるのを見て、一応 react-scriptsdevDependencies の方に移しておいた。

❯ git d package.json
diff --git a/package.json b/package.json
index b3fb928..5e13c2f 100644
--- a/package.json
+++ b/package.json
@@ -12,10 +12,12 @@
     "@types/react-dom": "^17.0.11",
     "react": "^17.0.2",
     "react-dom": "^17.0.2",
-    "react-scripts": "4.0.3",
     "typescript": "^4.4.4",
     "web-vitals": "^1.1.2"
   },
+  "devDependencies": {
+    "react-scripts": "4.0.3"
+  },
   "scripts": {
     "start": "react-scripts start",
     "build": "react-scripts build",

これでいいのかな?

❯ npm audit --production                                           
found 0 vulnerabilities

良さそう。ところで、Create React App は、そんなに開発が活発じゃなくなってるみたいね。ほほー。

We need regualr CRA maintainer · Issue #11180 · facebook/create-react-app · GitHub

ESLint

じゃ、ESLint。ここを読んで

Getting Started with ESLint - ESLint - Pluggable JavaScript linter

こうかな

❯ npm install eslint --save-dev

❯ npx eslint --init

--init を実行すると色々と質問されるので答えていくと設定が作られる。ちょっと気になったのでコードを探してみたら、この辺かな:

https://github.com/eslint/eslint/blob/a79c9f35d665c2bcc63267bdf359a8176e0a84ce/lib/init/config-initializer.js#L472

↓こんな感じで質問に答えた。airbnb のにしてみた。設定ファイルは、あとで TypeScript の設定を入れるときに JavaScript じゃないといけないみたいだから JavaScript で。

f:id:bufferings:20211116005447p:plain

package.json から ESLint の設定を消す

create-react-app で作られた package.json の中に ESLint の設定が入ってるんだけど、eslint --init.eslintrc.js が作成されたので、package.json の方は消しとく

❯ git d
diff --git a/package.json b/package.json
index 4a66a4a..123a630 100644
--- a/package.json
+++ b/package.json
@@ -32,12 +32,6 @@
     "test": "react-scripts test",
     "eject": "react-scripts eject"
   },
-  "eslintConfig": {
-    "extends": [
-      "react-app",
-      "react-app/jest"
-    ]
-  },
   "browserslist": {
     "production": [
       ">0.2%",

.eslintignore

ここを読んで

https://eslint.org/docs/user-guide/configuring/ignoring-code

.eslintignore ファイルを作っておくと良さそうなので追加

/**
!/src/

とりあえず src だけ対象にしてみたらいい?↓を参考にした

Gitignore - Exclude all except specific subdirectory · GitHub

TypeScript ESLint

を使ってるみたいなので、この辺を↓をざっくり読んだ

こうかな?

diff --git a/.eslintrc.js b/.eslintrc.js
index 8fab9f6..6660755 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -6,6 +6,12 @@ module.exports = {
   extends: [
     'plugin:react/recommended',
     'airbnb',
+    'airbnb-typescript',
+    'airbnb/hooks',
+    'plugin:@typescript-eslint/recommended',
+    'plugin:@typescript-eslint/recommended-requiring-type-checking',
+    'plugin:jest/recommended',
+    'prettier'
   ],
   parser: '@typescript-eslint/parser',
   parserOptions: {
@@ -14,10 +20,13 @@ module.exports = {
     },
     ecmaVersion: 12,
     sourceType: 'module',
+    tsconfigRootDir: __dirname,
+    project: ['./tsconfig.json'],
   },
   plugins: [
     'react',
     '@typescript-eslint',
+    'jest'
   ],
   rules: {
   },

__dirname を指定するのは、↓ここを読んでふむふむって思った。今回の場合は書かなくても良さそうだけど

airbnb-typescript の設定は、↓ここを読んでなるほどって思った

prettier のところは、↓ここを読んでほほーって思った。最後に書かないといけないのね

eslint-config-prettiereslint-config-airbnb-typescript を入れておいたー

❯ npm install --save-dev prettier eslint-config-prettier eslint-config-airbnb-typescript

Prettier の設定

.prettierrc.json を作成。↓をざっと眺めてみたけど、Single Quote を使いたいくらいかな。

{
  "singleQuote": true
}

それと prettier 自体も入れておいた

❯ npm install --save-dev --save-exact prettier

ちょっと修正

このままだと

ESLint: Unexpected unnamed function.(func-names)

って言われるから「ほうほう・・・じゃ、言われた通りに変更するか」って Arrow Function に変換したら、今度は

ESLint: Function component is not a function expression(react/function-component-definition)

って言われるのであった。なるほど?って、指示通りに変更したら、最初の状態に戻るやないかー。おーい。

ということで調べてみたら、どうも airbnb の設定みたいで、Issue と PR が出てる

配列で指定できるようにしてほしいって PR が最後のやつ。

コードを見てみたら TODO ついてたw

javascript/react.js at 1bc8cabd447ef9ce69d27ae70e67eb47daeffc21 · airbnb/javascript · GitHub

// TODO: investigate if setting namedComponents to expression vs declaration is problematic

なので、PR が取り込まれたら設定いらなくなると思うけど、今はとりあえずこんな風にしておけばいいかな

❯ git d                               
diff --git a/.eslintrc.js b/.eslintrc.js
index c2289a1..2641508 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -24,5 +24,13 @@ module.exports = {
     project: ['./tsconfig.json'],
   },
   plugins: ['react', '@typescript-eslint', 'jest'],
-  rules: {},
+  rules: {
+    'react/function-component-definition': [
+      2,
+      {
+        namedComponents: 'function-declaration',
+        unnamedComponents: 'function-expression',
+      },
+    ],
+  },
 };

上記の設定は↓のデフォルト値を参考にしておいた

reportWebVitals.ts

んー。このファイル、ESLint のエラーがでるんだけど

error Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator @typescript-eslint/no-floating-promises

よく分かんないから .eslintignore に追加しちゃえ!

/**
!/src/
reportWebVitals.ts

まいっか。いつか分かるときがくるでしょう。

あと、ついでに警告を指示通りに解決しておいた。型が定義してあるから、チェックしなくていいやろってことかな

❯ git d
diff --git a/src/reportWebVitals.ts b/src/reportWebVitals.ts
index 49a2a16..cfad7f0 100644
--- a/src/reportWebVitals.ts
+++ b/src/reportWebVitals.ts
@@ -1,7 +1,7 @@
 import { ReportHandler } from 'web-vitals';
 
 const reportWebVitals = (onPerfEntry?: ReportHandler) => {
-  if (onPerfEntry && onPerfEntry instanceof Function) {
+  if (onPerfEntry) {
     import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
       getCLS(onPerfEntry);
       getFID(onPerfEntry);

で、実行ー!

❯ npx eslint . --ext .js,.jsx,.ts,.tsx    

ヽ(=´▽`=)ノ 何も言われなくなった。それはそれで合ってるのか不安だけども。

WebStorm の設定

WebStorm に Prettier と ESLint の設定を入れておく。実は、この記事を書いてる途中から、この設定を入れてチェックしてたんだけれども。

Prettier

Preferences | Languages & Frameworks | JavaScript | Prettier

f:id:bufferings:20211116224305p:plain

フォーマッターかけたときと、保存したときに、Prettier が実行されるようにしてみた

ESLint

Preferences | Languages & Frameworks | JavaScript | Code Quality Tools | ESLint

f:id:bufferings:20211116224426p:plain

保存したら eslint --fix が実行されるようにしてみた

これで

保存したらフォーマッターがかかって eslint --fix が実行されるようになったっぽい。

はー。入り口から学ぶことがいっぱいあったなぁ。面白かった。これで React の勉強しやすくなるといいな。おしまい。