ReactでDatePicker(react-datepicker）+ reactstrap + formikを使う


## やりたいこと

datepickerを使うと、そこだけCSSが適用されなかったり、独自バリデーションとなるのを、ReactStrapで見た目を整え、Formikでバリデーションしたい。

## 完成

以下のような感じを目指す。

![スクリーンショット 2019-12-02 13.09.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/599f3d6f-0449-1b9e-5b0d-158da3cbc8fd.png "スクリーンショット 2019-12-02 13.09.29.png")


## 準備

作業場所と必要なモジュールをインストール。

```bash
create-react-app datepicker
cd datepicker
yarn add react-datepicker
yarn add bootstrap reactstrap moment formik yup
```

>npm install --save  bootstrap reactstrap moment formik yup


## 実装


ポイントはreact-datepickerのcustomInputでReactstrapのInputを指定しているところ。
dateのバリデーションはとりあえず当月以外が指定されたらエラーが出るようにしている。

```js:App.js
import React from 'react';
import './App.css';
import { Form, FormGroup, Label, Input, FormFeedback, Button } from 'reactstrap';
import { Formik } from 'formik';
import * as Yup from 'yup';
import moment from 'moment';

//react-datepicker
import DatePicker, { registerLocale } from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
//for locale ja
import ja from 'date-fns/locale/ja';
registerLocale('ja', ja);


class App extends React.Component {

    handleOnSubmit = (values) => {
        alert(JSON.stringify(values));
    }

    render() {
        return (
            <React.Fragment>
                <div className="container">
                    <Formik
                        initialValues={{ email: '', startDate: moment(new Date()).format('YYYY/MM/DD') }}
                        onSubmit={this.handleOnSubmit}
                        validationSchema={Yup.object().shape({
                            email: Yup.string().email().required(),
                            startDate: Yup.string().required().test('checkDate', '当月を指定して下さい。', (picked) => {
                                const pickedMonth = moment(new Date(picked)).month() + 1;
                                const thisMonth = moment(new Date()).month() + 1;
                                if (pickedMonth === thisMonth) {
                                    return true;
                                } else {
                                    return false;
                                }
                            }),
                        })}
                    >
                        {
                            ({ handleSubmit, handleChange, handleBlur, values, errors, touched, setFieldValue }) => (
                                <Form onSubmit={handleSubmit} className="col-8 my-5">
                                    <FormGroup >
                                        <Label for="email">Email</Label>
                                        <Input
                                            type="email"
                                            name="email"
                                            id="email"
                                            onChange={handleChange}
                                            onBlur={handleBlur}
                                            invalid={Boolean(touched.email && errors.email)}
                                        />
                                        <FormFeedback>
                                            {errors.email}
                                        </FormFeedback>
                                    </FormGroup>
                                    <FormGroup>
                                        <legend className="col-form-label">開始日時</legend>
                                        <DatePicker
                                            locale="ja"
                                            name="startDate"
                                            id="startDate"
                                            value={values.startDate}
                                            dateFormat="YYYY/MM/DD"
                                            customInput={<Input invalid={Boolean(errors.startDate)} />}
                                            onChange={date => setFieldValue("startDate", moment(date).format('YYYY/MM/DD'))}
                                        />
                                        <p className="text-danger small">{errors.startDate}</p>
                                    </FormGroup>
                                    <div className="my-3">
                                        <Button type="submit">送信</Button>
                                    </div>
                                </Form>
                            )
                        }
                    </Formik>
                </div>
            </React.Fragment>
        );
    }
}

export default App;

```