create-react-appで作成したReact+Material-UI開発環境のメモ

## 概要

create-react-appで作成したReact+Material-UI開発環境、を昨日から使い始めました！いろいろ詰まると思うので、それぞれメモっておきたいとおもいます。

とりあえず公開しておきますが、今後も随時追加していく予定です。

## 開発環境のつくりかた

まずは以下の2つのツールを使えるようにしておいて

```
npm install -g create-react-app
npm install -g serve
```

例えば react-test という開発環境を作成するとすると、以下を順に実行します。

```
create-react-app react-test
cd react-test
npm install material-ui --save
npm start
```

これでブラウザが起動してサンプルページが表示されますので、あとは src/App.js を修正するだけ！

完成したら以下を実行してブラウザで表示を確認し、問題なければ build フォルダをWebサーバーなどにアップロード＆公開して完了。

```
npm run build
serve -s build
```

詳しい経緯は [React開発環境のセットアップで挫折し、create-react-appに救われた件](https://qiita.com/yamachan360/items/efcff4bd14fe623807ab) を参考にしてみてください。

## テーマエラーが表示されてしまう

以下のように Material-UI のパーツを &lt;MuiThemeProvider&gt; タグで囲んでください。

```html
<MuiThemeProvider>
  <Chip onRequestDelete = {() => alert("delete")}>
    Chip test
  </Chip>
</MuiThemeProvider>
```

## アイコンが表示されない

JSX で以下のようにタブなどにアイコンを設定しても

```html
  <Tabs>
  <Tab
    icon={<FontIcon className="material-icons">home</FontIcon>}
    label="HOME"
  >
```

以下のようにアイコンではなく文字で表示されてしまう場合、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/cc70bf29-633a-232b-0f23-b6770c80f451.png)

Google が提供しているフォントアイコン用の以下のCSSが読み込まれていないのが原因のようです。なのでこのファイルをローカルに保存し、

```html
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
```

以下のように import してあげればokです。

```js
import './MaterialIcons.css';
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/4c728a65-4708-3df3-d12d-dc98733d6c63.png)

なおアイコンを探す場合は [Material icons - Material Design](https://material.io/icons/) からどうぞ。

## リストの値を覚えてくれない

値をひとつ選択できる [SelectField](http://www.material-ui.com/#/components/select-field) ですが、最初、以下のように簡単に書いたら値を覚えてくれませんでした。選択しても空のままです。

```html
<SelectField floatingLabelText="List selection">
  <MenuItem value={1} primaryText="categoiry1" />
  <MenuItem value={2} primaryText="categoiry2" />
  <MenuItem value={3} primaryText="categoiry3" />
</SelectField>
```

状態を覚えさせるためには、公式サイトのサンプルのように、クラス化する必要がありそうです。でも数多くある場合、いちいちクラス化するのも面倒ですよね？

とりあえず以下のように記述したら値を覚えてくれました。

```html
<SelectField floatingLabelText="List selection"
  value={this.state ? this.state.value : 1}
  onChange={(event, index, values) => this.setState({value:values})}
>
  <MenuItem value={1} primaryText="categoiry1" />
  <MenuItem value={2} primaryText="categoiry2" />
  <MenuItem value={3} primaryText="categoiry3" />
</SelectField>
```

クラス化しないと SelectField 内の state を初期化できない、なので最初に value 属性をセットする際に undefined エラーになる、のが問題のようでした。

そこでちょっと強引ですが、value 属性の式に、state が未定義の場合には初期値(今回は1)を渡すように処理を加えてみました。ちなみに onChange 式のほうは公式のクラス化するコードと同じです。

で、うまく動作するようにみえましたが… これは駄目でした。2個目の SelectField を追加すると、両者で値が連動してしまいます。つまり、state を共有してしまうようで、クラス変数になっちゃってる？感じの動きです。

なので上記のサンプルをちょっと修正した以下を利用しました。まず値を保持するために専用の変数を用意して、初期値をセットしておきます。

```js
var sf_value1 = 1;
```

後は処理を以下のように書き換えればok。

```html
<SelectField floatingLabelText="List selection"
  value={sf_value1}
  onChange={(event, index, values) => {sf_value1 = values; this.setState({value:values})}}
>
```

かなりベタな感じになりましたが、それぞれ別々のクラスを定義するよりはマシかと。

ただしこの方法だと、たぶん this.setState() でこの方法で実装した全てのSelectField に更新イベントが飛ぶとおもわれます。あまりに数が多かったり、リストの動的作成などで処理が重いものがあれば、ちゃんとクラス化したほうが良いとおもわれます。

こんど余裕があったら、複数あっても連動しない、簡単に使えるリスト部品が作れないか考えてみたいとおもいます。

## Node.js サーバーと通信できない

自作の Node.js アプリのフロント部分を React+Material-UI で書き直してみたのですが、アプリAPIへのアクセスが動作しなくて困りました。

自身の Node.js アプリは //localhost:6001/api/* でサービスを受けつけているのですが、create-react-app でプレビュー中のページは //localhost:3000/ なので、CORS(Cross-Origin Resource Sharing) 問題が発生してアクセスできません。ビルドして Node.js アプリ側に反映すれば動作しますが、時間がかかり面倒です。

たぶん create-react-app でプレビュー用に動作しているwebサーバーのヘッダに Access-Control-Allow-Origin: を設定すれば良いのですが、いまいちどう動作しているかわからず…

とりあえず現在は Chrome Extension の [CORS](https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi) で無理やりアクセスを許可させて動作確認しています。こんな感じで…

![image.png](https://qiita-image-store.s3.amazonaws.com/0/193519/13b8c321-217b-87c1-6b81-f02e87279853.png)


## おわりに

React + Material-UI を使い始めて2日ですが、開発環境さえ作ってしまえば、わりと使いやすく、かつ洗練されたUIで良いとオモイマス。既に手元のアプリを1つ、この環境に移植中…

ただReact、というか [Facebookのライセンス問題](https://qiita.com/exli3141/items/a36b9bc88d818efb3331) (Facebook社と特許で係争中の会社はコードを利用できない、的な)を知って、大手のプロジェクトでは利用できない可能性が高いな、とちょっと意欲が減退気味。どうしようかな…

【追記】MITライセンスになるようで、よかった！

ではまた！