5
3

はじめに

この記事では、React / TypeScript 環境で ESLint の Flat Config を利用する方法について記載します。

元々 ESLint の設定ファイルは .eslintrc.* でしたが、v9.0.0(2024年4月リリース)からは Flat Config (eslint.config.js) がデフォルトになっています。さらに v10.0.0(2024年末から2025年頭にリリース予定)では、.eslintrc.* が削除される予定です。1

そのため、Flat Config (eslint.config.js) を利用した設定方法を調べていきます。

開発環境

開発環境は以下の通りです。

  • Windows 11
  • VSCode
  • TypeScript 5.2.2
  • React 18.3.1
  • Vite 5.3.1
  • Node.js 20.15.0
  • npm 10.8.1
  • ESLint 8.57.0
  • @eslint/js 9.6.0
  • eslint-plugin-react 7.34.3
  • globals 15.8.0
  • typescript-eslint 7.15.0

Node.js は以下いずれかのバージョンにする必要があります。

Node.js (^18.18.0, ^20.9.0, or >=21.1.0)2

事前準備

Vite の react-ts テンプレートで React / TypeScript のプロジェクトを作成しておきます。

npm create vite@latest my-react-ts-app -- --template react-ts

詳細はこちら。

ESLint のインストールと自動設定

以下のコマンドで、ESLint 及び必要なパッケージのインストール、設定ファイル eslint.config.js の作成ができます。

npm init @eslint/config@latest

コマンド実行後、いくつか質問されるので、以下の選択をします。

image.png

React のプラグインは現時点(2024年7月)で ESLint v9 をサポートしていないので、今回は v8 をインストールします。

package.json には、以下のパッケージが追加されます。

package.json
{
  ...
  "devDependencies": {
    "@eslint/js": "^9.6.0",
    "eslint": "^8.57.0",
    "eslint-plugin-react": "^7.34.3",
    "globals": "^15.8.0",
    "typescript-eslint": "^7.15.0",
    ...
  }
}

加えて、設定ファイル eslint.config.js が作成されます。

eslint.config.js
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";

export default [
  { files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"] },
  { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } },
  { languageOptions: { globals: globals.browser } },
  pluginJs.configs.recommended,
  ...tseslint.configs.recommended,
  pluginReactConfig,
];

ESLint を実行します。

npx eslint src

ワーニングとエラーが表示されます。

Warning: React version not specified in eslint-plugin-react settings. See https://github.com/jsx-eslint/eslint-plugin-react#configuration .

C:\Users\ymori\Documents\GitHub\flat-config\src\App.tsx
  10:5   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  11:7   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  12:9   error  Using target="_blank" without rel="noreferrer" (which implies rel="noopener") is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations  react/jsx-no-target-blank
  12:9   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  13:11  error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  15:9   error  Using target="_blank" without rel="noreferrer" (which implies rel="noopener") is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations  react/jsx-no-target-blank
  15:9   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  16:11  error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  19:7   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  20:7   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  21:9   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  24:9   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  25:16  error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  28:7   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope

 14 problems (14 errors, 0 warnings)
  2 errors and 0 warnings potentially fixable with the `--fix` option.

ワーニングの修正

まずはワーニングを修正します。

Warning: React version not specified in eslint-plugin-react settings.
See https://github.com/jsx-eslint/eslint-plugin-react#configuration .

ワーニングメッセージ通り https://github.com/jsx-eslint/eslint-plugin-react を確認すると、version の値を "detect" にすることで、自動的に利用中の React バージョンを検知してくれるという記載があります。

// React version. "detect" automatically picks the version you have installed.
// You can also use 16.0, 16.3, etc, if you want to override the detected value.
// It will default to "latest" and warn if missing, and to "detect" in the future

また、version"settings > react 内に記載があります。
そのため、settings > react > version: "detect" という構造で、eslint.config.js に設定を追加します。

eslint.config.js
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";

export default [
  {
    files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"],
    // 追加
    settings: {
      react: {
        version: "detect",
      },
    },
    plugins: {
      pluginReactConfig,
    },
  },
  { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } },
  { languageOptions: { globals: globals.browser } },
  pluginJs.configs.recommended,
  ...tseslint.configs.recommended,
  pluginReactConfig,
];

ESLint を実行します。

npx eslint src

ワーニングが解消されていることを確認できます。

C:\Users\ymori\Documents\GitHub\flat-config\src\App.tsx
  10:5   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  11:7   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  12:9   error  Using target="_blank" without rel="noreferrer" (which implies rel="noopener") is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations  react/jsx-no-target-blank
  12:9   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  13:11  error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  15:9   error  Using target="_blank" without rel="noreferrer" (which implies rel="noopener") is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations  react/jsx-no-target-blank
  15:9   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  16:11  error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  19:7   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  20:7   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  21:9   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  24:9   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  25:16  error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope
  28:7   error  'React' must be in scope when using JSX                                                                                                      
                                          react/react-in-jsx-scope

 14 problems (14 errors, 0 warnings)
  2 errors and 0 warnings potentially fixable with the `--fix` option.

エラーの修正

エラーは以下の2種類表示されています。

'React' must be in scope when using JSX react/react-in-jsx-scope
Using target="_blank" without rel="noreferrer" (which implies rel="noopener") isa security risk in older browsers: 
see https://mathiasbynens.github.io/rel-noopener/#recommendations  react/jsx-no-target-blank

react-in-jsx-scope

ひとつ目のエラーについては、React 17 以上では、無効化すべきルールです。今回は React 18 を利用しているので、無効化します。

If you are using the new JSX transform from React 17, you should disable this rule by extending react/jsx-runtime in your eslint config (add "plugin:react/jsx-runtime" to "extends").

ただ、ドキュメントには、"extends""plugin:react/jsx-runtime" を追加するよう記載がありますが、Flat Config には "extends" が存在しません。eslint-plugin-react には、Shareable configs という共有設定ファイルが3つあり、その中に eslint-plugin-react/configs/jsx-runtime があります。そのため、eslint-plugin-react/configs/jsx-runtime をインポートして、eslint.config.js に追加します。

eslint.config.js
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";
import pluginReactJSXRuntime from "eslint-plugin-react/configs/jsx-runtime.js"; // 追加

export default [
  {
    files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"],
    settings: {
      react: {
        version: "detect",
      },
    },
    plugins: {
      pluginReactConfig,
    },
  },
  { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } },
  { languageOptions: { globals: globals.browser } },
  pluginJs.configs.recommended,
  ...tseslint.configs.recommended,
  pluginReactConfig,
  pluginReactJSXRuntime, // 追加
];

ESLint を実行します。

npx eslint src

'React' must be in scope when using JSX react/react-in-jsx-scope エラーが解消されていることを確認できます。

C:\Users\ymori\Documents\GitHub\flat-config\src\App.tsx
  12:9  error  Using target="_blank" without rel="noreferrer" (which implies rel="noopener") is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations  react/jsx-no-target-blank
  15:9  error  Using target="_blank" without rel="noreferrer" (which implies rel="noopener") is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations  react/jsx-no-target-blank

 2 problems (2 errors, 0 warnings)
  2 errors and 0 warnings potentially fixable with the `--fix` option.

react/jsx-no-target-blank

もう一つのエラーは、セキュリティ上よろしくない部分なので、コードを修正します。ドキュメントの記載通り target='_blank' を使っている a タグに rel='noreferrer' を追加します。

When creating a JSX element that has an a tag, it is often desired to have the link open in a new tab using the target='_blank' attribute. Using this attribute unaccompanied by rel='noreferrer', however, is a severe security vulnerability (see noreferrer docs and noopener docs for more details) This rules requires that you accompany target='_blank' attributes with rel='noreferrer'.

ESLint を実行すると、エラーが全て解消されていることを確認できます。

npx eslint src

所感

  • .eslintrc.* との差異が思ったより大きい
  • Flat Config に追いついていない ESLint プラグインもけっこうある(プラグイン自体追いついていない、ドキュメントが追いついていないケースがある)
  • react-in-jsx-scope デフォルトで無効にしておいて欲しい

参考

  1. https://eslint.org/blog/2023/10/flat-config-rollout-plans/

  2. https://eslint.org/docs/latest/use/getting-started#prerequisites

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3