LoginSignup
2
0

More than 1 year has passed since last update.

ReactHookFormとMaterial-UI v5でHTML5に頼らないDatePickerを作る

Last updated at Posted at 2021-09-30

はじめに

  • Material-UIでUIを作る(せっかくなので出たばかりのv5を使いたい)
  • ReactHookFormで入力制御したい

といった条件下で、最初にHTML5に頼った日付入力<TextField type="date">で作ってみたところ
Chromeで表示したら↓のようにラベルの初期表示と"年/月/日"の表示が被って酷いことになっていた。
image.png
また、HTML5頼りのDatepickerだとまだうまく動かないブラウザがあるといった情報もちらほら見られたことから
Material-UI LabにあるDatePickerで日付入力を構築してみたのが本記事。
(LabはまだCoreに移せていないものという扱いらしいが、DatePickerについてはHTML5での入力が一般化してきたらCoreに移る前に無くなりそうな予感はしている)

目次

  1. 環境
  2. ソースコード
  3. 機能概要
  4. 参考文献

環境

"@date-io/date-fns": "^2.11.0",
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
"@mui/icons-material": "^5.0.0-rc.1",
"@mui/lab": "^5.0.0-alpha.48",
"@mui/material": "^5.0.0-rc.1",
"date-fns": "^2.24.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-hook-form": "^7.15.3",

ソースコード


Sample.tsx
import { DatePicker, LocalizationProvider } from '@mui/lab'
import DateAdapter from '@mui/lab/AdapterDateFns'
import { Box, Button, TextField } from '@mui/material'
import { format } from 'date-fns'
import { ja } from 'date-fns/locale'
import React from 'react'
import { Controller, useForm } from 'react-hook-form'

// 日付入力フォーム
type InputDateProps = {
  id: string
  label: string
  control: any
  errors: any
}
const InputDate: React.FC<InputDateProps> = ({
  id,
  label,
  control,
  errors,
}) => {
  return (
    <Controller
      name={id}
      control={control}
      rules={{
        //必須入力チェック
        required: '必須入力項目です',
        //入力内容が日付として読み取れない状態を通さないためのチェック
        validate: {
          dateCheck: (value) =>
            value.toString() !== 'Invalid Date' || '日付形式で入力してください',
        },
      }}
      render={({ field }) => (
        <LocalizationProvider dateAdapter={DateAdapter} locale={ja}>
          <DatePicker
            {...field}
            label={label}
            mask="____/__/__"
            renderInput={(params) => (
              <TextField
                {...params}
                margin="normal"
                id={id}
                error={Boolean(errors[id])}
                helperText={errors[id] && errors[id].message}
              />
            )}
          />
        </LocalizationProvider>
      )}
    />
  )
}

//入力項目の使用
const Sample: React.FC<{}> = () => {
  const initValue = {
    date: '',
  }

  const {
    control,
    handleSubmit,
    formState: { errors },
  } = useForm<typeof initValue>({ defaultValues: initValue })

  const onSubmit = (e) => {
    //データ内容確認
    console.log(e)
    //Dateからstringに変換して取得
    console.log(format(e.date, 'yyyy/MM/dd'))
  }

  return (
    <Box p={4}>
      <form onSubmit={handleSubmit(onSubmit)}>
        <Box mb={4}>
          <InputDate id="date" label="日付" control={control} errors={errors} />
        </Box>
        <Button variant="contained" type="submit">
          submit
        </Button>
      </form>
    </Box>
  )
}
export default Sample


機能概要

画面表示

初期表示

image.png

日付選択

image.png

バリデーション

必須チェック
image.png
入力形式チェック
image.png

入力データの取得結果

image.png
文字列で扱いたかったがDate型で取得される模様
⇒とりあえずonSubmitの処理でyyyy/MM/dd形式にフォーマットして使うことにした

参考文献

2
0
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
2
0