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

SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92

クロスオリジン分離対応を実施

Next.jsで生成したサイトで特定のページのみnoindexを設定する

タグに紐づく記事一覧ページはnoindexにした

Next.jsでAdsenseタグを埋め込んだら Only one AdSense head tag supported per page エラーが発生

Only one AdSense head tag supported per page. The second tag is ignored.

VercelのPreview環境に固定のサブドメインを割り当てる

X-Robots-Tagは付与されないので注意