pure react で `<select>` を使う

# 概要
特別なライブラリを入れることなくHTMLの`<select>`をReactで動くようにします。

# サンプル
ネット通販などで時間帯指定をする場面を例にしています。
[create-react-app](https://github.com/facebookincubator/create-react-app) で開始しています。

```App.js
import React, { Component } from 'react';
import SelectPlain from './components/SelectPlain';
import SelectPlainOnChange from './components/SelectPlainOnChange';
import SelectDynamicOptions from "./components/SelectDynamicOptions";

class App extends Component {
  render() {
    return (
      <div>
        <h1>お届け時間帯</h1>
        <div>(1) <SelectPlain/> </div>
        <div>(2) <SelectPlainOnChange/> </div>
        <div>(3) <SelectDynamicOptions/> </div>
      </div>
    );
  }
}

export default App;
```

## (1) 静的な`<select>`の例
reactを使う意味がないとか言わない。
初期値は`value`ではなく`defaultValue`を使います。

```js
import React, { Component } from 'react';

class App extends Component {
  render() {
    return (
      <select defaultValue="14to16">
        <option value="9to12">9:00-12:00</option>
        <option value="12to14">12:00-14:00</option>
        <option value="14to16">14:00-16:00</option>
        <option value="16to18">16:00-18:00</option>
        <option value="18to20">18:00-20:00</option>
        <option value="20to21">20:00-21:00</option>
      </select>
    );
  }
}

export default App;
```

`defaultValue`を`value`にしていると、下記のような警告が出ます。

```警告メッセージ（改行追加）.
Warning: Failed form propType: 
You provided a `value` prop to a form field without
an `onChange` handler. This will render a read-only field.
If the field should be mutable use `defaultValue`.
Otherwise, set either `onChange` or `readOnly`.
```

onChangeを使う場合は(2)のようにしてください。

## (2) (1)で`defaultValue`を使わない例
`value`を使ったときの警告メッセージに「onChangeを使え」とあるので、こちらで実装します。

```SelectPlainOnChange.js
import React, {Component} from 'react';

export default class SelectPlainOnChange extends Component {
  
  constructor(props) {
    super(props);
    this.state = {
      selectedValue: '14to16'
    };
  }
  
  render() {
    return (
      <select
          value={this.state.selectedValue}
          onChange={ e => this.setState({selectedValue: e.target.value}) }>
        <option value="9to12">9:00-12:00</option>
        <option value="12to14">12:00-14:00</option>
        <option value="14to16">14:00-16:00</option>
        <option value="16to18">16:00-18:00</option>
        <option value="18to20">18:00-20:00</option>
        <option value="20to21">20:00-21:00</option>
      </select>
    );
  }
}
```

`onChange`や`value`の値が正しくないと`<select>`をクリックして変更しても値が変わらない、という現象に遭遇します。

## (3) `<option>`の繰り返しを排除する
(1)をリファクタリングして、`<option>`の繰り返しを排除します。
繰り返しの中で異なる部分は`value`属性とoption要素値なので、これらを`data`という名前でオブジェクトに格納します。

```js
import React, {Component} from 'react';

export default class SelectDynamicOptions extends Component {
  
  constructor(props) {
    super(props);
    this.data = [
      { value: '9to12',  label: '9:00-12:00'  },
      { value: '12to14', label: '12:00-14:00' },
      { value: '14to16', label: '14:00-16:00' },
      { value: '16to18', label: '16:00-18:00' },
      { value: '18to20', label: '18:00-20:00' },
      { value: '20to21', label: '20:00-21:00' },
    ];
  }
  
  render() {
    return (
      <select defaultValue="14to16">
        { this.data.map( d => <option value={d.value}>{d.label}</option>)}
      </select>
    );
  }
}

```

実用的には、`constructor`内で`props`を受け取り`this.data`に渡す感じになりますね。

# まとめと雑記
* Reactに不慣れなのでHTMLっぽく書いてReactに移すという順序で書いていますが、意外とつまづいたので記事にしました。
* 外部ライブラリ[react-select](https://github.com/JedWatson/react-select)を使ってみたものの、多要素とかぶったときに`<option>`が隠れてしまってウオオとなったのが本当の動機です。あと外部依存はできるだけ少なくしたい。
* 個人的には動的に`<option>`の数や属性を変えたいという要件が出るまでは(1)の書き方でいいと思っています。