React × TypeScript 環境構築

## はじめに
今回は`create-react-app`でReact×TypeScriptプロジェクトを作成したあと、
開発をさらにスムーズにする以下の4つのライブラリをインストールします。

* `ESLint`
コーディングルールを厳密に指定するツール
* `Prettier`
 コード自動整形ツール
* `hot-loder` 
ソース保存時自動でブラウザをリロードするツール
* `type` 
React固有の型を登録するツール

上記はいずれも現場でよく使われるライブラリなので今回も導入したいと思います。

## 動作環境
* ``macOS Catalina``
* ``node: 16.13.0``
* ``npm: 6.14.8``
* ``yarn: 1.22.10``

## React×TypeScriptプロジェクト作成

```terminal:ターミナル
$ npx create-react-app react-ts-project --template typescript
```

おなじみ`create-react-app`の末尾に`--template typescript`を付けるだけ。
`react-ts-project`はお好きなプロジェクト名に変更して大丈夫です。
最後に`Happy hacking!` と表示されればプロジェクト作成は完了です。

## 起動確認
作成されたディレクトリに入り起動確認。

```terminal:ターミナル
$ cd react-ts-project
$ yarn start
```
`http://localhost:3000`で以下の画面が確認できればOKなので、`control + c`で一旦サーバーは止めて大丈夫です。
![スクリーンショット 2022-01-22 20.17.30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603142/2faa7b1f-aa0d-956a-a1f5-4dace5edf509.jpeg)


## ESLintのインストール
まずは下記コマンドで`.eslintrc.js`を作成します。

```terminal:ターミナル
$ yarn run eslint --init
```
その際以下9問の質問に答えます。

```terminal:ターミナル
? How would you like to use ESLint?
  To check syntax only
  To check syntax and find problems
❯ To check syntax, find problems, and enforce code style を選択

? What type of modules does your project use?
❯ JavaScript modules (import/export) を選択
  CommonJS (require/exports)
  None of these

? Which framework does your project use?
❯ React を選択
  Vue.js
  None of these

? Does your project use TypeScript?
❯ Yes を選択

? Where does your code run?
❯ Browser を選択
  Node

? How would you like to define a style for your project?
❯ Use a popular style guide を選択
  Answer questions about your style

? Which style guide do you want to follow?
❯ Airbnb: https://github.com/airbnb/javascript を選択
  Standard: https://github.com/standard/standard
  Google: https://github.com/google/eslint-config-google
  XO: https://github.com/xojs/eslint-config-xo

? What format do you want your config file to be in?     
❯ JavaScript を選択
  YAML
  JSON

...中略...

? Would you like to install them now with npm?
❯ Yes を選択

```
作成完了したら下記コマンドで`ESLint`をインストール。

```terminal:ターミナル
$ yarn add -D @typescript-eslint/eslint-plugin @typescript-eslint/parser
```
末尾につけている`@typescript-eslint/parser`は
ESLintがTypeScriptを理解する為に必要なプラグインなので一緒にインストールしてます。

今回はAirbnbのスタイルガイドを導入するので以下のコマンドを入力し、質問には「y」を選択します。

```terminal:ターミナル
$ npx install-peerdeps --dev eslint-config-airbnb

It seems as if you are using Yarn. Would you like to use Yarn for the installation? (y/n)
❯ y を選択
```
続いて.eslintrc.jsを以下のように編集します。

```js:.eslintrc.js
module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    'plugin:react/recommended',
    'airbnb',
// ----↓追記↓----
    'airbnb/hooks',
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
    'prettier',
// ----↑追記↑----
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 12,
    sourceType: 'module',
// ----↓追記↓----
    tsconfigRootDir: __dirname,
    project: ['./tsconfig.json'],
// ----↑追記↑----
  },
  plugins: [
    'react'
    '@typescript-eslint',
  ],
// ----↓追記↓----
  ignorePatterns: [
    '.eslintrc.js'
  ],
// ----↑追記↑----
  rules: {
// ----↓追記↓----
    'no-use-before-define': "off",
    "@typescript-eslint/no-use-before-define": "off",
    'import/prefer-default-export': "off",
    'import/extensions': [
      'error',
      {
        js: 'never',
        jsx: 'never',
        ts: 'never',
        tsx: 'never',
      },
    ],
    'react/function-component-definition': [
      2,
      {
        namedComponents: 'arrow-function',
      },
    ],
    'react/jsx-filename-extension': [
      'error',
      {
        extensions: ['.jsx', '.tsx'],
      },
    ],
    'react/react-in-jsx-scope': 'off',
    'no-void': [
      'error',
      {
        allowAsStatement: true,
      },
    ],
// ----↑追記↑----
  },
// ----↓追記↓----
  settings: {
    'import/resolver': {
      node: {
        paths: ['src'],
        extensions: ['.js', '.jsx', '.ts', '.tsx']
      },
    },
  },
// ----↑追記↑----
},

```

ディレクトリルート（私の場合はreact-ts-project配下）に.eslintignore を作成し以下のように記述します。

```plaintext:.eslintignore
build/
public/
**/node_modules/
*.config.js
.*lintrc.js
/*.*
```

## prettier
`prettier`をインストールします。

```terminal:ターミナル
$ yarn add -D prettier eslint-config-prettier
```

ディレクトリルートに.prettierrc.js を作成してフォーマットのルールを決めます。

```js:.prettierrc.js
module.exports = {
  printWidth: 120,
  singleQuote: true,
  semi: false,
}
```
今回は上記のように設定しますが、お好みでカスタマイズ可能です。
Prettier公式：[Options - Prettier](https://prettier.io/docs/en/options.html)

## hot-loader
`hot-loder`をインストール。

```terminal:ターミナル
$ yarn add react-dom@npm:@hot-loader/react-dom
```

## type
`type`をインストール。

```terminal:ターミナル
$ yarn add -D @types/react
```

## ソースを編集
最後に、エラーを解消するためにソースコードを編集します。

```tsx:src/App.test.tsx
// 以下を削除
import React from 'react';
```

```tsx:src/App.tsx
import React from 'react';
// ↓に変更
import { VFC } from 'react';

// 中略

function App() {
// ↓に変更
const App: VFC = () => (
// ↓削除
  return (

// 中略

// ↓削除
}
```

```tsx:src/reportWebVitals.ts
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
// ↓に変更
const reportWebVitals = (onPerfEntry?: ReportHandler): void => {

import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
// ↓に変更
void import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
```

下記コマンドで再度サーバーを立ち上げます。

```terminal:ターミナル
$ yarn start
```

これで最初と同じReactの画面が表示されれば環境構築完了です！
お疲れさまでした！