React + Typescript + Sass + MDC Web の環境を新規で作る

## React + Typescript + Sass + MDC Web の環境を新規で作る
プログラミングは、たいてい環境構築が最も大変です。

React単体の環境構築はできても、TypescriptやSass、Material-Design-Component(MDC)を組み込んでゆくと、得体の知れないエラーと格闘する羽目になったりします。

本記事では、なるべく困らずに開発をスタートできるよう、手順を記します。
本記事は、2020年3月22日時点で動作確認しています。

### 参考記事：MDC-webのチュートリアル

[MDC-webの公式チュートリアル](https://github.com/material-components/material-components-web-react)があります（廃止されるようですが）。
これを参考に環境を構築します。

### 1.React + Typescriptを導入する

最初に、create-react-appを使用して、React+Typescriptを一気に導入します。
my-appの部分はプロジェクト名なので、好きに変えて構いません。

``` :ターミナル
npx create-react-app my-app --template typescript
```

プロジェクトができたら、その中に移動してビルドします。

``` :ターミナル
cd my-app
npm run build
```
最初のビルドは通ります。

``` :ターミナル
npm start
```
を実行すると、Reactの初期画面が表示されます。

<img width="483" alt="スクリーンショット 2020-03-22 06.44.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3605/070a6076-580e-d296-d68d-8d013285efe3.png">


### 2.MDCを導入する

MDC-Reactを導入します。

``` :ターミナル
npm install @material/react-button
```
で、コンポーネントをダウンロードします。

### 3.Sassを導入する

ターミナルで以下を実行し、環境変数を追加します。

``` :ターミナル
// macの場合
export SASS_PATH=./node_modules

// windowsの場合
SET SASS_PATH=.\node_modules
```
Sassモジュールをダウンロードします。

``` :ターミナル
npm install node-sass
```
src/App.cssファイルを、App.scssにリネームします。

``` :ターミナル
mv ./src/App.css ./src/App.scss
```

### 4.App.scssを編集する

App.scssをテキストエディタで編集し、2行の@import文を冒頭に挿入します。

``` ./src/App.scss

@import "@material/react-button/index.scss";
@import "./react-button-overrides";

...
```
srcフォルダ内にreact-button-overrides.scssファイルを新規に作成し、以下の文をコピペして保存します。

``` ./src/react-button-overrides.scss 
@import "@material/button/mixins";

.button-alternate {
  @include mdc-button-container-fill-color(lightblue);
}
```
### 5.App.tsxを編集する

src/App.tsxファイルをテキストエディタで開き、以下の文をコピペして保存します。元のコードは全部上書きで消します。

``` src/App.tsx
import React, {Component} from 'react';
import Button from '@material/react-button';

import './App.scss';
// add the appropriate line(s) in Step 3a if you are using compiled CSS instead.

class App extends Component {
  render() {
    return (
      <div>
        <Button
          raised
          className='button-alternate'
          onClick={() => console.log('clicked!')}
        >
          Click Me!
        </Button>
      </div>
    );
  }
}

export default App;
```

このままでは、Typescriptの規約でコンパイルエラーが出るので、規則を変えます。
tsconfig.json に、下記の１行を挿入します。
``` tsconfig.json
    "noImplicitAny": false,
```

気分的には15行目あたりが収まりがいい気がしますね。

``` tsconfig.json
14    "forceConsistentCasingInFileNames": true,
15    "noImplicitAny": false, // ここに挿入
16    "module": "esnext",
```

### 5.reactの型定義を更新

最後に、reactの型定義を最新に更新します。

``` :ターミナル
yarn upgrade @types/react@latest
```

ここまで来れば、再度ビルドが通るようになるはずです。

``` :ターミナル
npm run build
```

当たり前ですが、実行もできます。

``` :ターミナル
npm start
```

<img width="217" alt="スクリーンショット 2020-03-22 07.30.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3605/780032bd-a287-fc09-abe3-fe4ba35e2ed6.png">

MDC-webのボタンのデモアプリが実行できました。

---
### おまけ：エラーとその原因
---


#### SassError: File to import not found or unreadable: @material/elevation/mixins.

MDCのコンポーネントが、Sassモジュールから読めていません。

``` :ターミナル
// macの場合
export SASS_PATH=./node_modules

// windowsの場合
SET SASS_PATH=.\node_modules
```
を実行しましょう。

#### Could not find a declaration file for module 'react'.
reactの定義ファイルがない・・と言ってますが、そもそもありません。
これは、Typescriptの設定が厳しいために発生するエラーです。
tsconfig.jsonを編集して、設定を緩めましょう。以下の文を挿入します。

``` tsconfig.json
    "noImplicitAny": false,
```

#### JSX element type 'App' is not a constructor function for JSX elements.

reactの型定義が古いことで発生するエラーで、Appクラスが読めなくなります。

``` :ターミナル
yarn upgrade @types/react@latest
```
で解決します。