ReactでDatePickerとRadioボタンを扱う

#ReactにおけるDatePickerとmoment

[React Bootstrap DatePicker](https://github.com/pushtell/react-bootstrap-date-picker)は日付をフォームに入力する際にカレンダーを表示させて、カレンダーの日付をクリックすると選択した日付がフォームに入る機能。
これを使うためには、react-bootstrap-date-pickerをインストールする。
```
npm install react-bootstrap-date-picker --save
```

また、以下のようにimportする。

```js 
import DatePicker from 'react-datepicker'
import 'react-datepicker/dist/react-datepicker.css’
```

moment()は時刻をDate型で取得する関数。
何も渡さずに行うと、Date型で現在の時刻を返す。
UTCミリ秒を渡した場合は、Date型に変換して返す。

* UTCは1970年１月１日00:00:00から経過した時間をミリ秒単位で表したもの


moment()を使うには、以下をimportする。

```js
import moment from 'moment'
```


DatePicker＆moment記述例

```js
this.state = { 
　　　sample: moment() 
}

DatehandleChange_sample(date) {
　　　this.setState({ sample: date })
}

<DatePicker
　　　selected={this.state.sample}
　　　name=“sample”
　　　value={this.state.sample}
　　　onChange={(e) => this.DatehandleChange_sample(e)}
/>
```
デフォルトだと01/01/2017のように、年が後ろに表示されるので、以下のようにコンストラクタなどでロケールをjaにするとよい。

```js
moment.locale('ja')
```

と書いておくと2017/01/01の表記になる。


DatePickerで定義されたフォームのvalue(上記の``value={this.state.sample}``)を直接指定して取れるのはDate型ではなく、フォームに入力されている日付が文字列で取り出される。
（フォームに2017/01/01と表示されていたら、「2017/01/01」という文字列が取り出される）

もしDatePickerで定義したフォームのvalueに文字列を入れて、内容を更新しようとした場合以下の警告が出る
>
moment.js:293 Deprecation warning: value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.

この状態だとカレンダーは出るが、カレンダーの日付をクリックすると、エラーが出る。

>Uncaught TypeError: we.isSame is not a function

このエラーが出るのは、DatePickerの変数はDate型で無ければならないため。
文字列をDate型に変換したい場合は、以下のように、Date.parse()やgetTime()を使ってUTCミリ秒に変換した数値をmoment()に渡す必要がある。


```js
state = { sample: '2017/01/01" }
moment(Date.parse( this.state.sample )　)//UTCミリ秒に変更した数値をmomentに渡している
```

明細行にDatePickerが含まれ、それが動的に追加される処理などの場合、変数と一緒に関数も同時に生成する必要があった。[ソースコード](https://github.com/hiroki-morishita/vtecxblank/blob/master/src/components/fermata_input.js)

```js
//stateで行を管理するrowsを作成
this.state ={
　　rows: [1]
}

>
//
this.setReturn_date = []
this.setReturn_date[0] = function (date) {
　　this.setState({ return_date1: date })
}.bind(this)

>
addRow() {
　　　this.setState(
　　　　　(prevState) => ({
　　　　　　　rows: prevState.rows.concat([prevState.rows.length + 1])
　　　　　})
　　　)
　　　const return_date = 'return_date' + (this.state.rows.length + 1)
　　　this.setReturn_date[this.state.rows.length] = function (date) {
　　　　　this.setState({ [return_date]: date })
　　　}.bind(this)
}

>
HobbyForm(row: number) {
const return_date = 'return_date' + row
return(
　　<tbody key={row.toString()}>
　　　　<td>
　　　　　　<Col sm={12}>
　　　　　　　　<FormGroup controlId={return_date}>
　　　　　　　　　　<DatePicker selected={this.state[return_date]}
　　　　　　　　　　　　　　　　　name={return_date}
　　　　　　　　 　　　　　　　　　value={this.state[return_date]}
　　　　　　　　　　　　　　　onChange={(e) => this.setReturn_date[row-1](e)} />
　　　　　　　　</FormGroup>
　　　　　　</Col>
　　　　</td>
　　</tbody>
)
}
```

***



#Reactにおけるラジオボタン

ラジオボタンを使うには、以下をimportする。
>import React from 'react'
import Radio from 'react-bootstrap'


記述例

```js
state = { sample:''}

RadioChange(e:InputEvent){
　　this.setState({ sample: e.target.id })
}

<FormGroup controlId="publication">
<Col xs={10}sm={10}md={10}lg={10}xl={10}>
<Radio id="sample1" name="sample_name" checked={this.state.sample === 'sample1'} onChange={(e) => this.RadioChange(e)} inline>SAMPLE1</Radio>
<Radio id="sample2" name="sample_name" checked={this.state.sample === 'sample2'} onChange={(e) => this.RadioChange(e)} inline>SAMPLE2</Radio>
<Radio id="sample3" name="sample_name" checked={this.state.sample === 'sample3'} onChange={(e) => this.RadioChange(e)} inline>SAMPLE3</Radio>
</Col>
</FormGroup>
```

* ReactのRadioボタンでは、checkedがtrueかfalseでチェックされているかどうかを判断する。
    * this.state.sampleに最後に押されたボタンを管理させる。
    * sample1のRadioボタンが押されていたら、this.state.sampleにはsample1が入り、{this.state.sample ==='sample1}が成立してtrueになる。


#JSONのキーが変数のときは[]でくくる。

setStateなどでhoge変数のキーを変更するときは

```js
setState( { [hoge]:true } )
```


のように[]で括る。

#stateの孫の変数の変更方法


stateの子を変更するときは

```js
this.setState({children:1}) //OK
```
で変更可能、しかしstateの孫の変数をsetStateで直接変更をすることは出来ない。

```js
this.setState({children.gChildren:2}) //NG
```
孫の変数をsetStateで変えたいときは、以下のように関数を呼んで子の中身全体を変える。

```js
this.state = {feed : {}}

1 this.setState(
2               (prevState) => //ここのprevStateを16行目のprevStateに渡す
3			     ({feed: ((prevState) => { //16行目のprevStateを受取り、以下の処理
4					if (!prevState.feed.entry[0].bill.items) {
5						prevState.feed.entry[0].bill.items = []
6					
7					}
8					prevState.feed.entry[0].bill.items.push({
9						        brand_name: '',
10								   item_no: '',
11								 item_name: '',
12						   usage_situation: '',
13							   return_date: moment(),
14					})
15					return prevState.feed	
16				 })(prevState)//ここのprevStateを３行目のprevStateに渡す
17				})
18)
```