LoginSignup
5
4

More than 5 years have passed since last update.

ReactでDatePickerとRadioボタンを扱う

Last updated at Posted at 2017-09-05

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)
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4