react-hook-formとReact Datepickerを組み合わせる

公開日時

Next.jsアプリケーションでフォームを扱う必要があったので、React Hook Formを利用した。

また、カレンダーから日時選択ができるようにしたかったのでReact Datepickerと組み合わせることにした。

hook-form
  • components/DatePicker.tsx

Hook FormのControllerのドキュメントを参考にDatePicker用のコンポーネントを作成。

import 'react-datepicker/dist/react-datepicker.css'

import React from 'react'
import ReactDatePicker from 'react-datepicker'
import { Control, Controller, Path } from 'react-hook-form'

type Props<T> = {
  label: string
  name: Path<T>
  error?: string
  control: Control<T>
  timeIntervals?: number
}

export const DatePicker = <T,>({
  label,
  name,
  control,
  error,
  timeIntervals = 15,
}: Props<T>) => {
  return (
    <>
      <label htmlFor={name}>
        {label}
      </label>
      <div>
        <Controller
          control={control}
          name={name}
          render={({ field: { onChange, value } }) => (
            <ReactDatePicker
              dateFormat="yyyy-MM-dd HH:mm"
              showTimeSelect
              timeIntervals={timeIntervals}
              onChange={onChange}
              selected={value as Date}
            />
          )}
        />
      </div>
      <span>{error}</span>
    </>
  )
}

ジェネリクスの型引数を指定する際に <T> がコンポーネントとして認識されてしまいハマった。

const DatePicker = <T>(...) ではなく const DatePicker = <T,>(...) と指定する必要があった。

  • pages/edit.tsx

あとは useForm を使用しているページでDatePickerコンポーネントを呼び出せばReact Datepickerによる日付選択が可能になる。

import { DatePicker } from '@/components/DatePicker'

type FormValues = {
  datetime: string;
} 

const EditPage = () => {
  const {
    control,
    formState: { errors },
  } = useForm<FormValues>()

  return (
    <DatePicker
      label="datetime"
      name="datetime"
      control={control}
      error={errors.datetime?.message}
    />
  )
}

export default EditPage

参考


Related #next.js

FigmaでSVG Octocatを作る その3

アウトライン化大事

Next.jsプロジェクトのGoogle Analytics V3をV4に更新する

トラッキングIDの差し替えのみで対応が完了した

Vercelで指定のブランチのみデプロイを実行する

Ignored Build Stepを設定した