react-hook-formとReact Datepickerを組み合わせる
Next.jsアプリケーションでフォームを扱う必要があったので、React Hook Formを利用した。
また、カレンダーから日時選択ができるようにしたかったのでReact Datepickerと組み合わせることにした。
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