DatePicker
React

ReactでDatePickerとRadioボタンを扱う

More than 1 year has passed since last update.

ReactにおけるDatePickerとmoment

React Bootstrap DatePickerは日付をフォームに入力する際にカレンダーを表示させて、カレンダーの日付をクリックすると選択した日付がフォームに入る機能。
これを使うためには、react-bootstrap-date-pickerをインストールする。

npm install react-bootstrap-date-picker --save

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

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

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

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

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

import moment from 'moment'

DatePicker&moment記述例

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にするとよい。

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()に渡す必要がある。

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

明細行にDatePickerが含まれ、それが動的に追加される処理などの場合、変数と一緒に関数も同時に生成する必要があった。ソースコード

//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'

記述例

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変数のキーを変更するときは

setState( { [hoge]:true } )

のように[]で括る。

stateの孫の変数の変更方法

stateの子を変更するときは

this.setState({children:1}) //OK

で変更可能、しかしstateの孫の変数をsetStateで直接変更をすることは出来ない。

this.setState({children.gChildren:2}) //NG

孫の変数をsetStateで変えたいときは、以下のように関数を呼んで子の中身全体を変える。

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を3行目のprevStateに渡す
17              })
18)