React Datepickerの使い方を徹底解説


React Datepickerの使い方を徹底解説: 基本から高度なカスタマイズ、フォーム連携まで網羅

ウェブアプリケーション開発において、ユーザーが日付を選択する機能は非常に一般的です。予約システム、タスク管理、イベントスケジューラーなど、様々な場面で必要とされます。Reactでこの機能を実装する際に、ゼロから全てを構築するのは大変な作業です。そこで活躍するのが、多機能で柔軟なReact Datepickerライブラリです。

この記事では、React Datepickerの基本的な使い方から、高度なカスタマイズ、国際化、フォーム連携、バリデーションまで、徹底的に解説します。約5000語にわたる詳細な説明と豊富なコード例を通じて、あなたがReact Datepickerを自在に使いこなせるようになることを目指します。

1. はじめに

React Datepickerの概要と利点

React Datepickerは、Reactのためのシンプルかつ再利用可能なDatepickerコンポーネントです。npmパッケージとして提供されており、Reactプロジェクトに簡単に統合できます。多くのカスタマイズオプションを提供しており、アプリケーションの要件に合わせて柔軟に見た目や動作を変更できます。

主な利点としては、以下が挙げられます。

  • シンプルさ: npm install react-datepickerで簡単に導入できます。
  • 柔軟なカスタマイズ: 見た目、日付範囲、無効化する日付、時間選択など、幅広いカスタマイズが可能です。
  • 国際化対応: 多言語に対応しており、様々なロケールで日付を表示できます。
  • アクセシビリティ: WAI-ARIAに準拠しており、キーボード操作やスクリーンリーダーにも対応しています。
  • 依存関係: date-fnsなどの一般的な日付ライブラリと連携して動作します。(以前はMoment.jsが主流でしたが、現在はdate-fnsが推奨されています)

なぜReact Datepickerを選ぶのか

Reactエコシステムには他にもDatepickerコンポーネントが存在しますが、React Datepickerはその成熟度、豊富な機能、活発なコミュニティサポート、そして高いカスタマイズ性から、多くのプロジェクトで採用されています。特に、多岐にわたる要件を持つアプリケーションや、グローバルな展開を視野に入れたアプリケーションにおいて、その真価を発揮します。

記事の目的と対象読者

この記事は、React開発者向けに書かれています。Reactの基本的な概念(コンポーネント、props, state, Hooksなど)を理解している方を対象としています。React Datepickerを使ったことがない方でも、この記事を読めば基本的な使い方から応用までを習得できるよう、段階的に解説を進めます。既にReact Datepickerを使っている方にとっても、より高度な機能やカスタマイズ方法を知るための参考になるでしょう。

この記事を通じて、あなたは以下のことができるようになります。

  • React Datepickerをプロジェクトにインストールし、基本的な日付選択機能を実装する。
  • 日付範囲選択、時間選択、月/年選択などの高度な機能を利用する。
  • 特定の期間の制限や、特定の日付/時間の無効化を設定する。
  • カスタム入力フィールドやカレンダー表示を独自のデザインで実装する。
  • 国際化対応を行い、様々な言語で表示する。
  • フォームライブラリ(react-hook-formなど)と連携し、フォームの一部として利用する。
  • 基本的なバリデーションを実装する。

さあ、React Datepickerの世界へ飛び込みましょう!

2. 準備: インストール

React Datepickerを使うためには、まずライブラリをプロジェクトにインストールする必要があります。また、日付の処理には外部ライブラリが推奨されているため、今回は公式ドキュメントでも推奨されているdate-fnsを合わせてインストールします。

npmまたはyarnを使ったインストール方法

ターミナルを開き、あなたのReactプロジェクトのルートディレクトリで以下のコマンドを実行します。

npmの場合:

bash
npm install react-datepicker date-fns

yarnの場合:

bash
yarn add react-datepicker date-fns

これにより、react-datepickerとその依存ライブラリであるdate-fnsがプロジェクトに追加されます。

必要なCSSのインポート方法

React Datepickerはデフォルトのスタイリングを提供しています。これを利用するには、アプリケーションのエントリポイント(例: src/index.jsまたはsrc/App.js)や、Datepickerを使用するコンポーネントのファイルで、提供されているCSSファイルをインポートする必要があります。

一般的には、src/App.jsやそれに相当する場所でインポートするのが最も簡単です。

“`jsx
// src/App.js または src/index.js など
import React from ‘react’;
import ReactDOM from ‘react-dom/client’;
import ‘./index.css’;
import App from ‘./App’;
// React DatepickerのデフォルトCSSをインポート
import “react-datepicker/dist/react-datepicker.css”;
import reportWebVitals from ‘./reportWebVitals’;

const root = ReactDOM.createRoot(document.getElementById(‘root’));
root.render(



);

// reportWebVitals(console.log))などを残す場合はそのまま
reportWebVitals();
“`

このCSSをインポートすることで、特に何もスタイリングを設定しなくても、機能的なカレンダーUIが表示されるようになります。後ほど、このデフォルトスタイルをカスタマイズする方法についても解説します。

これでReact Datepickerを使うための準備は完了です。

3. 基本的な使い方

React Datepickerをあなたのコンポーネントで使用する最も基本的な方法を見てみましょう。

最小限のコードでDatePickerを表示する

react-datepickerパッケージからDatePickerコンポーネントをインポートし、JSX内で使用します。

“`jsx
import React from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”; // CSSも忘れずにインポート

function MyDatePickerComponent() {
return (

日付を選択してください

);
}

export default MyDatePickerComponent;
“`

このコードを実行すると、入力フィールドが表示され、それをクリックするとカレンダーがポップアップ表示されます。ただし、現時点では日付を選択しても、その値はどこにも保存されず、表示も更新されません。

selected propで日付を選択状態にする

DatePickerコンポーネントで選択された日付を管理するには、Reactのstateを使用するのが一般的です。selected propには、現在選択されている日付(Dateオブジェクト)を渡します。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;

function MyDatePickerComponent() {
// 選択された日付を管理するstate
const [selectedDate, setSelectedDate] = useState(null); // 初期値はnull(何も選択されていない状態)

return (

日付を選択してください

{/ selected propにstateの値を渡す /}

);
}

export default MyDatePickerComponent;
“`

このコードでは、useState(null)selectedDateというstate変数を作成し、初期値をnullに設定しています。そして、DatePickerselected propにこのselectedDateを渡しています。

しかし、このままではやはり日付を選択してもstateが更新されないため、表示は変わりません。次に、日付変更をハンドリングする方法を見てみましょう。

onChange propで日付の変更をハンドリングする

DatePickerで日付が選択されたり、入力フィールドの値が変更されたりすると、onChange propに渡された関数が呼び出されます。この関数は、新しい日付を表すDateオブジェクトを引数として受け取ります。

このonChangeイベントを利用して、stateを更新することで、選択された日付を入力フィールドに表示させることができます。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;

function MyDatePickerComponent() {
const [selectedDate, setSelectedDate] = useState(null);

// 日付が変更されたときに呼び出される関数
const handleDateChange = (date) => {
setSelectedDate(date); // stateを更新
};

return (

日付を選択してください


{/ デバッグ用に選択された日付を表示してみる /}
{selectedDate &&

選択された日付: {selectedDate.toDateString()}

}

);
}

export default MyDatePickerComponent;
“`

これで、DatePickerコンポーネントは完全に機能するようになります。カレンダーから日付を選択したり、入力フィールドに直接日付を入力したりすると、selectedDate stateが更新され、入力フィールドの表示も更新されます。また、handleDateChange関数内で、選択された日付を使って他の処理(例えば、フォームの他のフィールドを更新したり、APIを呼び出したり)を行うことができます。

stateを使った日付の管理方法

前述の例では、useStateフックを使ってselectedDate stateを管理しました。これは最も一般的な方法です。selected propに渡す値は、JavaScriptの標準Dateオブジェクト、null、またはundefinedである必要があります。

date-fnsなどのライブラリを使う場合でも、DatePickerコンポーネント自体はJavaScriptのDateオブジェクトを扱います。date-fnsの関数を使って日付の操作(フォーマット、計算など)を行った結果をDateオブジェクトとしてselected propに渡す、という形になります。

例: 特定の初期日付を設定する場合

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
import { setHours, setMinutes } from ‘date-fns’; // date-fnsを使って特定の時間を設定する場合

function MyDatePickerComponent() {
// 初期値として今日の日付を設定
const [selectedDate, setSelectedDate] = useState(new Date());

// または、特定の日付と時間を設定する場合 (例: 今日 10:30)
// const [selectedDate, setSelectedDate] = useState(
// setHours(setMinutes(new Date(), 30), 10)
// );

const handleDateChange = (date) => {
setSelectedDate(date);
};

return (

日付を選択してください

);
}

export default MyDatePickerComponent;
“`

useStateの初期値にnew Date()を渡すと、コンポーネメントがマウントされた時点の今日の日付がデフォルトで選択された状態になります。

簡単なスタイリング(CSSのインポート)

セクション2で述べたように、import "react-datepicker/dist/react-datepicker.css"; を行うだけで、ある程度のスタイリングが適用されます。

しかし、アプリケーション全体のデザインに合わせてスタイリングを調整したい場合がほとんどです。デフォルトのCSSは、特定のCSSクラス名(例: .react-datepicker, .react-datepicker__header, .react-datepicker__dayなど)を使用しています。これらのクラスをターゲットに、あなたのCSSファイルでスタイルを上書きすることで、カスタマイズが可能です。

例: カレンダーの背景色を変更する

“`css
/ src/App.css またはあなたのCSSファイル /
.react-datepicker {
border-color: #007bff; / 例:青い枠線 /
font-family: ‘Arial’, sans-serif; / 例:フォント変更 /
}

.react-datepicker__header {
background-color: #007bff; / 例:ヘッダーの背景色を青に /
color: white; / 例:ヘッダーの文字色を白に /
}

.react-datepicker__current-month {
color: white; / 例:現在の月の文字色を白に /
}

.react-datepicker__day–selected {
background-color: #28a745; / 例:選択日の背景色を緑に /
color: white;
}

/ ホバー時のスタイルなど、他の要素も同様にカスタマイズ可能 /
.react-datepicker__day:hover {
background-color: #e9e9e9;
}

/ 例: 特定の無効な日付にスタイルを適用 /
.react-datepicker__day–disabled {
color: #ccc;
cursor: default;
}
“`

これらのクラス名を把握し、必要に応じてCSSを記述することで、React Datepickerの見た目を自由にカスタマイズできます。後ほど、より詳細なスタイリング方法や、styled-componentsなどと連携する方法についても触れます。

基本的な使い方はこれで終わりです。次に、React Datepickerが提供する様々な高度な機能とカスタマイズオプションについて詳しく見ていきましょう。

4. 高度な機能とカスタマイズ

React Datepickerは、基本的な日付選択だけでなく、時間選択、日付範囲選択、特定の期間の制限、表示形式の変更など、多くの高度な機能を提供しています。ここでは、これらの機能の使い方を一つずつ見ていきます。

日付範囲の選択 (Date Range Selection)

旅行の予約や期間指定など、開始日と終了日の両方を選択する必要がある場合、React Datepickerは日付範囲選択モードを提供します。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;

function DateRangePickerComponent() {
// 開始日と終了日をそれぞれstateで管理
const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);

// DatePickerのonChangeイベントハンドラ
// selectsStart と selectsEnd を使う場合、onChangeには選択された日付一つが渡される
const onChange = (dates) => {
const [start, end] = dates; // datesは [開始日, 終了日] の配列で渡される
setStartDate(start);
setEndDate(end);
};

return (

日付範囲を選択してください

{/ selectsRange propをtrueにする /}
{/ selected には開始日、endDate には終了日を渡す /}
{/ onChange は、開始日と終了日の配列を受け取る関数にする /}

{/ 選択された範囲を表示 /}
{startDate && endDate && (

選択された期間: {startDate.toDateString()} – {endDate.toDateString()}

)}
{startDate && !endDate && (

開始日: {startDate.toDateString()}

)}

);
}

export default DateRangePickerComponent;
“`

selectsRange prop:
このpropをtrueに設定すると、DatePickerは日付範囲選択モードになります。ユーザーが最初の日付をクリックするとそれが開始日となり、次にクリックした日付が終了日となります。

startDate, endDate prop:
それぞれ、範囲の開始日と終了日を表すDateオブジェクトを渡します。これらのpropを設定することで、選択状態が表示されます。

onChange prop:
selectsRangetrueの場合、onChangeハンドラに渡される引数は、選択された日付の配列 [開始日, 終了日] となります。ユーザーが開始日だけを選択した状態では [開始日, null]、両方選択した状態では [開始日, 終了日] となります。この配列を受け取って、適切なstateを更新します。

また、selectsStartselectsEndを個別のDatePickerコンポーネントに適用して連携させることもできます。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;

function SeparateDateRangePickers() {
const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);

return (

個別DatePickerでの日付範囲選択

{‘ ‘}
setStartDate(date)} // 個別DatePickerなので、dateを受け取る
selectsStart // これが開始日のPickerであることを示す
startDate={startDate}
endDate={endDate}
/>

{‘ ‘}
setEndDate(date)} // 個別DatePickerなので、dateを受け取る
selectsEnd // これが終了日のPickerであることを示す
startDate={startDate} // 開始日Pickerの状態を共有
endDate={endDate} // 終了日Pickerの状態を共有
minDate={startDate} // 終了日は開始日以降である必要がある
/>

{/ 選択された範囲を表示 /}
{startDate && endDate && (

選択された期間: {startDate.toDateString()} – {endDate.toDateString()}

)}

);
}

export default SeparateDateRangePickers;
“`

この方法では、2つのDatePickerコンポーネントを使用し、それぞれにselectsStartまたはselectsEnd propを設定します。そして、両方のDatePickerに同じstartDateendDateのstateを渡すことで連携させます。終了日PickerにはminDate={startDate}を設定することで、開始日より前の日付を選択できないように制限しています。

時間選択 (Time Selection)

日付だけでなく時間も選択したい場合は、時間選択機能を有効にします。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
// date-fnsを使って時間の初期値を設定する場合
import { setHours, setMinutes } from ‘date-fns’;

function DateTimePickerComponent() {
// 初期値を今日の 10:30 に設定する場合
const [selectedDateTime, setSelectedDateTime] = useState(
setHours(setMinutes(new Date(), 30), 10)
);
// 初期値を null にする場合
// const [selectedDateTime, setSelectedDateTime] = useState(null);

const handleDateTimeChange = (date) => {
setSelectedDateTime(date);
};

return (

日付と時間を選択してください


{/ 選択された日付と時間を表示 /}
{selectedDateTime && (

選択された日時: {selectedDateTime.toString()}

)}

);
}

export default DateTimePickerComponent;
“`

showTimeSelect prop:
このpropをtrueに設定すると、カレンダーの下に時間選択用のリストが表示されます。

showTimeSelectOnly prop:
日付選択機能なしで、時間だけを選択するPickerにしたい場合は、代わりにshowTimeSelectOnlytrueに設定します。

dateFormat prop:
日付と時間を一緒に表示する場合、dateFormat propで表示形式を指定します。date-fnsのフォーマット文字列を使用できます(例: yyyy/MM/dd HH:mm)。指定しない場合、デフォルトの形式になります。

timeFormat prop:
時間選択ドロップダウンの表示形式を指定します(例: HH:mm, h:mm aa)。

timeIntervals prop:
時間選択リストの刻みを分単位で指定します(例: 15分、30分)。

timeCaption prop:
時間選択リストの上に表示されるキャプションを設定します。

minTime, maxTime prop:
選択可能な時間の範囲を制限できます。これらはDateオブジェクトで、日付部分は無視され時間のみが参照されます。例えば、minTime={setHours(setMinutes(new Date(), 0), 9)} と設定すると、午前9時より前の時間は選択できなくなります。

jsx
// minTime, maxTime の例
<DatePicker
selected={selectedDateTime}
onChange={handleDateTimeChange}
showTimeSelect
dateFormat="yyyy/MM/dd HH:mm"
timeFormat="HH:mm"
timeIntervals={30}
minTime={setHours(setMinutes(new Date(), 0), 9)} // 9:00 以降
maxTime={setHours(setMinutes(new Date(), 30), 17)} // 17:30 まで
/>

月の選択 (Month Selection)

特定の月だけを選択したい場合は、月選択Pickerを使用します。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
// date-fnsで日付オブジェクトを作成する場合
import { setMonth, setYear } from ‘date-fns’;

function MonthPickerComponent() {
// 初期値を特定の月(例: 2023年7月)に設定する場合
const [selectedMonth, setSelectedMonth] = useState(
setYear(setMonth(new Date(), 6), 2023) // 月は0から始まるので7月は6
);
// 初期値を null にする場合
// const [selectedMonth, setSelectedMonth] = useState(null);

const handleMonthChange = (date) => {
setSelectedMonth(date);
};

return (

月を選択してください


{/ 選択された月を表示 /}
{selectedMonth && (

選択された月: {selectedMonth.getFullYear()}年{selectedMonth.getMonth() + 1}月

)}

);
}

export default MonthPickerComponent;
“`

showMonthYearPicker prop:
このpropをtrueに設定すると、DatePickerは月と年を選択するモードになります。カレンダーの日付部分は表示されず、月と年のリストが表示されます。

dateFormat prop:
月選択Pickerの場合、通常の日付形式ではなく、月と年のみを含む形式を指定します(例: yyyy年MM月, MM/yyyy)。

年の選択 (Year Selection)

特定の年だけを選択したい場合は、年選択Pickerを使用します。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
// date-fnsで日付オブジェクトを作成する場合
import { setYear } from ‘date-fns’;

function YearPickerComponent() {
// 初期値を特定の年(例: 2022年)に設定する場合
const [selectedYear, setSelectedYear] = useState(setYear(new Date(), 2022));
// 初期値を null にする場合
// const [selectedYear, setSelectedYear] = useState(null);

const handleYearChange = (date) => {
setSelectedYear(date);
};

return (

年を選択してください


{/ 選択された年を表示 /}
{selectedYear && (

選択された年: {selectedYear.getFullYear()}年

)}

);
}

export default YearPickerComponent;
“`

showYearPicker prop:
このpropをtrueに設定すると、DatePickerは年を選択するモードになります。年のリストが表示されます。

dateFormat prop:
年選択Pickerの場合、年のみを含む形式を指定します(例: yyyy年, yyyy)。

月の範囲選択 (Month Range Selection)

バージョン3.0以降では、selectsRangeshowMonthYearPickerを組み合わせることで、月の範囲選択も可能です。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;

function MonthRangePickerComponent() {
const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);

const onChange = (dates) => {
const [start, end] = dates;
setStartDate(start);
setEndDate(end);
};

return (

月の範囲を選択してください


{/ 選択された範囲を表示 /}
{startDate && endDate && (

選択された期間: {startDate.getFullYear()}年{startDate.getMonth() + 1}月 – {endDate.getFullYear()}年{endDate.getMonth() + 1}月

)}
{startDate && !endDate && (

開始月: {startDate.getFullYear()}年{startDate.getMonth() + 1}月

)}

);
}

export default MonthRangePickerComponent;
“`

selectsRangeshowMonthYearPickerを同時にtrueに設定することで、月の範囲を選択できます。onChangeハンドラには、日付範囲選択と同様に[開始月, 終了月]の形式でDateオブジェクトの配列が渡されます。

特定の年・月の表示制限

minDatemaxDate propを使って、ユーザーが選択できる日付の範囲を制限できます。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
import { addDays, subDays, addYears, subYears } from ‘date-fns’; // date-fnsを使って制限日付を作成

function DateRestrictionComponent() {
const [selectedDate, setSelectedDate] = useState(null);

const handleDateChange = (date) => {
setSelectedDate(date);
};

// 制限日付の例
const today = new Date();
const minSelectableDate = subDays(today, 7); // 今日から7日前まで
const maxSelectableDate = addDays(today, 30); // 今日から30日後まで

const minSelectableYear = subYears(today, 5); // 今から5年前
const maxSelectableYear = addYears(today, 5); // 今から5年後

return (

日付の範囲制限

今日から7日前~30日後までの日付を選択できます。

  <h2>年月の範囲制限 (showMonthYearPicker 使用時)</h2>
  <p>今から5年前~5年後までの年月を選択できます。</p>
    <DatePicker
        selected={selectedDate}
        onChange={handleDateChange}
        showMonthYearPicker
        dateFormat="yyyy/MM"
        minDate={minSelectableYear} // showMonthYearPicker時は年月の制限にも使える
        maxDate={maxSelectableYear} // showMonthYearPicker時は年月の制限にも使える
    />
</div>

);
}

export default DateRestrictionComponent;
“`

minDatemaxDateには、制限の開始/終了となるDateオブジェクトを渡します。これにより、カレンダー上で選択できない日付はグレーアウト表示されます。

showMonthYearPickershowYearPickerを使用している場合も、minDatemaxDateは年月の制限として機能します。

特定の日の無効化 (Disabling Dates)

特定の日付を選択できないようにするには、いくつかの方法があります。

excludeDates prop:
選択を無効にしたい日付のリストをDateオブジェクトの配列として渡します。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
import { addDays, subDays } from ‘date-fns’;

function ExcludeDatesComponent() {
const [selectedDate, setSelectedDate] = useState(null);
const today = new Date();

// 今日、明日、明後日を無効にする例
const excludedDates = [
today,
addDays(today, 1),
addDays(today, 2),
];

// 特定の曜日を無効にする例 (ここでは使わないが filterDate で可能)

const handleDateChange = (date) => {
setSelectedDate(date);
};

return (

特定の日付の無効化

今日、明日、明後日は選択できません。

);
}

export default ExcludeDatesComponent;
“`

includeDates prop:
逆に、指定した日付リストのみを選択可能にしたい場合にincludeDatesを使います。excludeDatesと同時に指定することも可能ですが、通常はどちらか一方を使います。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
import { addDays, subDays } from ‘date-fns’;

function IncludeDatesComponent() {
const [selectedDate, setSelectedDate] = useState(null);
const today = new Date();

// 今日から1週間後の日付だけを選択可能にする例
const includedDates = Array.from({ length: 7 }, (_, i) => addDays(today, i));

const handleDateChange = (date) => {
setSelectedDate(date);
};

return (

特定の日付のみ有効化

今日から7日間だけ選択できます。

);
}

export default IncludeDatesComponent;
“`

filterDate prop:
最も柔軟な方法として、filterDate propに関数を渡す方法があります。この関数は、カレンダーに表示される各日付(Dateオブジェクト)を引数として受け取り、その日付が選択可能であればtrue、無効であればfalseを返します。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
import { getDay } from ‘date-fns’; // date-fnsを使って曜日を取得

function FilterDateComponent() {
const [selectedDate, setSelectedDate] = useState(null);

const handleDateChange = (date) => {
setSelectedDate(date);
};

// 土曜日と日曜日を無効にする関数
// getDay() は日曜日を0、月曜日を1、…、土曜日を6として返す
const isWeekday = (date) => {
const day = getDay(date);
return day !== 0 && day !== 6; // 日曜日 (0) と土曜日 (6) 以外を許可
};

return (

カスタム関数で日付をフィルタリング

土曜日と日曜日は選択できません。

);
}

export default FilterDateComponent;
“`

filterDateを使えば、特定の曜日を無効にしたり、特定の条件を満たす日付(例: データベースから取得した予約済みのすべての日付)のみを無効にしたりといった複雑なフィルタリングが可能になります。

同様に、時間選択時にはexcludeTimesincludeTimesfilterTimeといったpropがあります。

デフォルト値 (Default Value)

セクション3の例でも示しましたが、selected propに初期値としてDateオブジェクトを渡すことで、Pickerを開いたときに特定の日付がデフォルトで選択された状態になります。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
import { addDays } from ‘date-fns’;

function DefaultValueComponent() {
// 初期値として今日から3日後の日付を設定
const [selectedDate, setSelectedDate] = useState(addDays(new Date(), 3));

const handleDateChange = (date) => {
setSelectedDate(date);
};

return (

デフォルト値の設定

);
}

export default DefaultValueComponent;
“`

入力フィールドのカスタマイズ (customInput)

DatePickerはデフォルトで<input type="text">要素をレンダリングしますが、これを完全にカスタマイズしたい場合があります。例えば、アイコンを追加したり、独自のスタイルを適用したり、react-hook-formなどのフォームライブラリと連携したりする場合です。

customInput propに、レンダリングしたいカスタム入力コンポーネントを渡します。このカスタムコンポーネントは、以下のpropを受け取る必要があります。

  • value: 現在の入力値(文字列)
  • onClick: 入力フィールドがクリックされたときにDatepickerを開くための関数
  • onChange: 入力値が変更されたときにDatepickerに通知するための関数(通常は不要ですが、直接入力を許可する場合に必要)
  • その他の入力フィールドに適用したい標準的なHTML属性(id, name, className, disabled, placeholderなど)

“`jsx
import React, { useState, forwardRef } from ‘react’; // forwardRef が必要
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
import { format } from ‘date-fns’; // date-fnsで日付をフォーマット

// カスタム入力コンポーネント
// forwardRef を使って ref を DatePicker に渡す必要がある
const CustomInput = forwardRef(({ value, onClick, placeholderText, disabled, readOnly }, ref) => (
<button
className=”example-custom-input” // カスタムスタイル用のクラス名
onClick={onClick}
ref={ref} // ref を渡す
disabled={disabled}
readOnly={readOnly}
style={{
padding: ’10px’,
border: ‘1px solid #ccc’,
borderRadius: ‘4px’,
backgroundColor: ‘white’,
cursor: disabled ? ‘not-allowed’ : ‘pointer’,
minWidth: ‘200px’,
textAlign: ‘left’
}}

{value || placeholderText} {/* 値があれば表示、なければプレースホルダー */}


));

function CustomInputComponent() {
const [selectedDate, setSelectedDate] = useState(null);

const handleDateChange = (date) => {
setSelectedDate(date);
};

return (

カスタム入力フィールドの使用

} // カスタムコンポーネントを渡す
placeholderText=”日付を選択…” // customInput を使う場合もプレースホルダーはここで指定
// dateFormat=”yyyy/MM/dd” // 表示形式は DatePicker 側で指定
/>

  <h2>カスタム入力 + 時間選択</h2>
  <DatePicker
    selected={selectedDate}
    onChange={handleDateChange}
    customInput={<CustomInput />}
    placeholderText="日時を選択..."
    showTimeSelect
    dateFormat="yyyy/MM/dd HH:mm"
    timeFormat="HH:mm"
    timeIntervals={15}
  />
</div>

);
}

export default CustomInputComponent;
“`

customInputを使用する場合、placeholderText, disabled, readOnlyなどのプロパティはDatePickerに渡す必要があります。これらの値はDatePickerが管理し、customInputコンポーネントにpropとして自動的に渡されます。

forwardRefを使用しているのは、DatePickerがカスタム入力要素に内部的にrefを設定する必要があるためです。カスタム入力コンポーネントでref propを受け取り、実際のDOM要素(この例ではbutton)に渡してください。

カスタム入力コンポーネントには、value propとして選択された日付の文字列(dateFormat propで指定された形式)が渡されます。このvalueをテキスト表示に利用できます。

また、DatePickerの他の便利な入力フィールド関連propとして、placeholderText, disabled, readOnly があります。

  • placeholderText: 入力フィールドに表示されるプレースホルダーテキスト。
  • disabled: 入力フィールドとカレンダーを無効化します。
  • readOnly: 入力フィールドからの直接入力を禁止し、カレンダーからの選択のみを許可します。

カレンダー表示のカスタマイズ

カレンダー自体の表示方法も様々なpropで制御できます。

  • inline: trueにすると、DatePickerが常に表示され、入力フィールドをクリックして開く必要がなくなります。
    jsx
    <DatePicker
    selected={selectedDate}
    onChange={handleDateChange}
    inline // 常にカレンダーを表示
    />

  • withPortal: trueにすると、カレンダーがReact Portalを使用してDOMの別の場所にレンダリングされます。これは、モーダルやオーバーレイ内でDatePickerを使用する場合に、z-indexの問題などを回避するのに役立ちます。
    jsx
    <DatePicker
    selected={selectedDate}
    onChange={handleDateChange}
    withPortal // ポータルを使ってレンダリング
    />

  • monthsShown: 表示する月数を指定します。複数の月を一度に表示できます。
    jsx
    <DatePicker
    selected={selectedDate}
    onChange={handleDateChange}
    monthsShown={2} // 2ヶ月表示
    />

  • showPreviousMonths: monthsShownと組み合わせて使用し、過去の月を先に表示するか(デフォルト)未来の月を先に表示するかを制御します。

  • 年・月ドロップダウン:

    • showMonthDropdown: 月の選択肢をドロップダウンで表示します。
    • showYearDropdown: 年の選択肢をドロップダウンで表示します。
    • dropdownMode="select": ドロップダウンを<select>要素としてレンダリングします。(デフォルトは"scroll"
    • scrollableYearDropdown: 年ドロップダウンをスクロール可能にし、表示される年数を制限せずに多くの年を表示できるようにします。
    • yearDropdownItemNumber: dropdownMode="scroll" の場合に表示する年の数を指定します。

    jsx
    <DatePicker
    selected={selectedDate}
    onChange={handleDateChange}
    showMonthDropdown // 月をドロップダウンで選択
    showYearDropdown // 年をドロップダウンで選択
    dropdownMode="select" // ドロップダウンを select タグで表示
    // scrollableYearDropdown // スクロール可能な年ドロップダウン (dropdownMode="scroll" 時)
    // yearDropdownItemNumber={10} // スクロール可能な年ドロップダウンに表示する年数 (dropdownMode="scroll" 時)
    />

  • カスタムヘッダー (renderCustomHeader): カレンダーのヘッダー部分(月と年の表示、前後の月への移動ボタンなど)を完全にカスタムレンダリングできます。このpropに関数を渡すと、その関数がヘッダーをレンダリングします。関数は現在の表示月やナビゲーション関数などを含むオブジェクトを受け取ります。

    “`jsx
    import React, { useState } from ‘react’;
    import DatePicker from ‘react-datepicker’;
    import “react-datepicker/dist/react-datepicker.css”;
    import { getMonth, getYear } from ‘date-fns’;
    import range from “lodash/range”; // 配列生成に lodash.range を使う例

    const years = range(1990, getYear(new Date()) + 1, 1); // 1990年から今年までの年リスト
    const months = [
    “1月”, “2月”, “3月”, “4月”, “5月”, “6月”,
    “7月”, “8月”, “9月”, “10月”, “11月”, “12月”
    ];

    function CustomHeaderComponent() {
    const [selectedDate, setSelectedDate] = useState(null);

    const handleDateChange = (date) => {
    setSelectedDate(date);
    };

    return (

    カスタムヘッダー

    (


    {/ 前月ボタン /}

            {/* 月ドロップダウン */}
            <select
              value={getMonth(date)} // 現在表示されている月のインデックス (0-11)
              onChange={({ target: { value } }) => changeMonth(parseInt(value, 10))}
              style={{ marginLeft: '10px', marginRight: '5px' }}
            >
              {months.map((option, index) => (
                <option key={option} value={index}>
                  {option}
                </option>
              ))}
            </select>
    
            {/* 年ドロップダウン */}
            <select
              value={getYear(date)} // 現在表示されている年
              onChange={({ target: { value } }) => changeYear(parseInt(value, 10))}
               style={{ marginRight: '10px' }}
            >
              {years.map((option) => (
                <option key={option} value={option}>
                  {option}
                </option>
              ))}
            </select>
    
            {/* 次月ボタン */}
            <button onClick={increaseMonth} disabled={nextMonthButtonDisabled}>
              {">"}
            </button>
          </div>
        )}
      />
    </div>
    

    );
    }

    export default CustomHeaderComponent;
    ``renderCustomHeader`は非常に強力で、ドロップダウンだけでなく、独自のボタンや表示を追加するなど、ヘッダー部分を完全に制御できます。渡される引数オブジェクトのプロパティを確認して、必要な機能を利用してください。

日付表示形式のカスタマイズ (dateFormat)

DatePickerの入力フィールドやカレンダーヘッダーに表示される日付の形式は、dateFormat propで指定します。このpropには、日付ライブラリ(通常はdate-fns)が解釈できる形式文字列を渡します。

date-fnsの主なフォーマット文字列例:

  • yyyy: 4桁の年 (例: 2023)
  • yy: 2桁の年 (例: 23)
  • MM: 2桁の月 (例: 07)
  • M: 1桁または2桁の月 (例: 7)
  • dd: 2桁の日 (例: 01)
  • d: 1桁または2桁の日 (例: 1)
  • EEEE: 曜日のフルネーム (例: Wednesday)
  • E..E: 曜日の省略名 (例: Wed)
  • HH: 24時間表示の時間 (例: 13)
  • hh: 12時間表示の時間 (例: 01)
  • mm: 分 (例: 05)
  • ss: 秒 (例: 09)
  • aa: 午前/午後 (例: PM)

dateFormatのデフォルト値はMM/dd/yyyyですが、日本のアプリケーションではyyyy/MM/ddyyyy年MM月dd日などが一般的です。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;

function DateFormatComponent() {
const [selectedDate, setSelectedDate] = useState(new Date());

const handleDateChange = (date) => {
setSelectedDate(date);
};

return (

日付表示形式のカスタマイズ

);
}

export default DateFormatComponent;
“`

dateFormatは表示形式を指定するだけでなく、ユーザーが入力フィールドに直接日付を入力した場合の解析形式としても使用されます。複数の形式で入力を受け付けたい場合は、strictParsing={false}dateFormat={['format1', 'format2']}のように配列で指定することも可能です。ただし、複数の形式を受け付ける場合は、解析が意図通りに行われるか注意が必要です。

カレンダーナビゲーション

カレンダーの月を移動する方法もいくつか制御できます。

  • forceShowMonthNavigation: trueにすると、minDate/maxDateで制限されていても、ナビゲーションボタン(前月・次月)が常に表示されます。ただし、制限範囲外の月への移動はできません。
  • showDisabledMonthNavigation: trueにすると、minDate/maxDateで無効化された月へのナビゲーションボタンがグレー表示されるのではなく、有効な月へのボタンと同様に表示されますが、クリックしても無効になります。

これらのプロパティは、minDate/maxDateを使った制限を設定した場合に、ユーザーインターフェースの挙動を調整するために使用されます。

ハイライト (Highlighting Dates)

特定の日付に背景色などをつけてハイライト表示したい場合があります。例えば、イベントのある日や特別な日などです。highlightDates propに、ハイライトしたい日付のリストを渡します。

highlightDatesDateオブジェクトの配列を受け取ります。より高度なハイライト(例えば、日付ごとに異なる色を付ける)には、オブジェクトの配列を渡すことができます。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
import { addDays, getDay } from ‘date-fns’;

function HighlightDatesComponent() {
const [selectedDate, setSelectedDate] = useState(null);
const today = new Date();

// ハイライトする日付のリスト (単なるDateオブジェクトの配列)
const simpleHighlightDates = [
addDays(today, 3),
addDays(today, 5),
addDays(today, 10),
];

// 曜日ごとに異なる色でハイライトする例
// オブジェクトの配列を渡す
// 各オブジェクトは { “react-datepicker__day–highlighted-[modifier]”: datesArray } の形式
const complexHighlightDates = [
{
“react-datepicker__day–highlighted-monday”: [ // 月曜日をハイライト (カスタムクラス名)
addDays(today, 1), addDays(today, 8), addDays(today, 15)
],
“react-datepicker__day–highlighted-friday”: [ // 金曜日をハイライト (カスタムクラス名)
addDays(today, 4), addDays(today, 11), addDays(today, 18)
],
},
];

// カスタムCSSで .react-datepicker__day–highlighted-monday や
// .react-datepicker__day–highlighted-friday のスタイルを定義する必要がある

const handleDateChange = (date) => {
setSelectedDate(date);
};

return (

日付のハイライト

特定のイベント日などをハイライト表示します。

);
}

export default HighlightDatesComponent;
“`

オブジェクトの配列を使ってハイライトする場合、指定したキー(例: "react-datepicker__day--highlighted-monday")がそのままCSSクラス名として該当する日付セルに適用されます。このクラス名に対するスタイルをCSSで定義する必要があります。

“`css
/ src/App.css またはあなたのCSSファイル /
/ highlightDates を使って追加されたカスタムクラスのスタイル例 /
.react-datepicker__day–highlighted-monday {
background-color: #d8f0d8; / 薄い緑 /
color: #2e8b57; / 暗い緑 /
}

.react-datepicker__day–highlighted-friday {
background-color: #f0d8d8; / 薄い赤 /
color: #b22222; / レンガ色 /
}
“`

追加情報 (Adding Additional Information)

renderDayContents propを使用すると、カレンダーの日付セル内にカスタムコンテンツをレンダリングできます。例えば、日付の下に小さなアイコンやテキストを追加する場合などに役立ちます。

このpropには関数を渡します。関数は、レンダリング対象の日付(Dateオブジェクト)と、カレンダーの月表示が現在の月であるかどうかを示すフラグisCurrentMonthを受け取ります。関数が返すJSX要素が日付の数字の周りに表示されます。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
import { getDay } from ‘date-fns’;

function RenderDayContentsComponent() {
const [selectedDate, setSelectedDate] = useState(null);

const handleDateChange = (date) => {
setSelectedDate(date);
};

// 曜日によって異なるマークを表示する例
const renderDayContents = (dayOfMonth, date, isCurrentMonth) => {
const dayOfWeek = getDay(date); // 日曜日: 0, 月曜日: 1, …
let indicator = ”;
if (isCurrentMonth) {
if (dayOfWeek === 0) indicator = ‘☀️’; // 日曜日
if (dayOfWeek === 6) indicator = ‘🎉’; // 土曜日
if (dayOfMonth === 15) indicator = ‘⭐’; // 毎月15日
}

return (
  <div className="custom-day-content">
    {dayOfMonth}
    {indicator && <span className="day-indicator">{indicator}</span>}
  </div>
);

};

// custom-day-content と day-indicator のスタイルをCSSで定義する必要がある
// 例:
/
.custom-day-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%; // セルいっぱいに広げる
}
.day-indicator {
font-size: 0.6em;
margin-top: 2px;
}
/

return (

日付セル内のカスタムコンテンツ

);
}

export default RenderDayContentsComponent;
“`

この機能を使えば、日付の横や下にイベントの有無を示すマークを表示したり、簡単な予定情報を表示したりといったことが可能です。

CSSによるスタイリング

React Datepickerは、react-datepicker/dist/react-datepicker.cssにデフォルトスタイルを提供しています。このCSSは多くのクラス名を使用しており、これらをターゲットにスタイルを上書きすることでカスタマイズを行います。

主なCSSクラスの例:

  • .react-datepicker: Datepickerコンポーネント全体
  • .react-datepicker__month-container: 月ビューのコンテナ
  • .react-datepicker__header: 月/年セレクタとナビゲーションボタンを含むヘッダー
  • .react-datepicker__month: カレンダーの月ビュー
  • .react-datepicker__week: 週の行
  • .react-datepicker__day: 日付セル
  • .react-datepicker__day--selected: 選択されている日付
  • .react-datepicker__day--keyboard-selected: キーボードでフォーカスされている日付
  • .react-datepicker__day--in-range: 日付範囲選択で範囲内の日付
  • .react-datepicker__day--range-start: 日付範囲の開始日
  • .react-datepicker__day--range-end: 日付範囲の終了日
  • .react-datepicker__day--disabled: 無効化された日付
  • .react-datepicker__day--outside-month: 現在表示されている月以外の月の日付
  • .react-datepicker__day--highlighted: highlightDatesでハイライトされた日付 (プレフィックス + modifier)
  • .react-datepicker__time-container: 時間選択コンテナ
  • .react-datepicker__time .react-datepicker__time-box: 時間選択リスト

カスタマイズ方法:

  1. グローバルCSSでの上書き:
    import "react-datepicker/dist/react-datepicker.css"; の後に、あなたのカスタムCSSファイルをインポートし、そこで上記のクラス名をターゲットにスタイルを記述します。詳細度を高くする必要がある場合があります。

    “`css
    / src/App.css /
    @import ‘~react-datepicker/dist/react-datepicker.css’; / デフォルトCSSをインポート /

    / カスタムスタイルの上書き /
    .react-datepicker__day–selected,
    .react-datepicker__day–keyboard-selected {
    background-color: #ff6347; / トマト色 /
    color: white;
    }

    .react-datepicker__day:hover {
    background-color: #f0f0f0;
    }
    ``
    ( Sass/SCSS を使用している場合、
    @importのパスはnode_modules` を起点に記述できます。)

  2. CSS Modules:
    CSS Modulesを使用する場合、デフォルトCSSをインポートし、それを基にスタイルを定義します。

    “`jsx
    // src/components/MyDatePicker.module.css
    @import ‘~react-datepicker/dist/react-datepicker.css’;

    / 特定のクラスを上書き /
    .myCustomDatePicker .react-datepicker {
    border-color: purple;
    }

    .myCustomDatePicker .react-datepicker__day–selected {
    background-color: rebeccapurple;
    }
    “`

    “`jsx
    // src/components/MyDatePicker.js
    import React, { useState } from ‘react’;
    import DatePicker from ‘react-datepicker’;
    import styles from ‘./MyDatePicker.module.css’; // CSS Modulesをインポート

    function MyDatePicker() {
    const [selectedDate, setSelectedDate] = useState(null);

    return (
        <div className={styles.myCustomDatePicker}> {/* ラッパー要素にモジュールクラスを適用 */}
            <DatePicker
                selected={selectedDate}
                onChange={date => setSelectedDate(date)}
                // DatePicker自体にクラスを適用する prop は limited なので、
                // ラッパー div にクラスを適用し、その中で子孫セレクタを使うのが一般的
            />
        </div>
    );
    

    }
    ``
    React Datepickerは、DatePickerコンポーネント自体に直接
    classNamepropを渡すことができますが、これが内部の子要素に全て継承されるわけではありません。そのため、多くの場合、DatePickerコンポーネントをラッパー要素で囲み、そのラッパー要素にCSS Moduleのクラスを適用し、子孫セレクタ(例:.myCustomDatePicker .react-datepicker__day–selected`)を使ってスタイリングするのが効果的です。

  3. Styled Componentsなど:
    Styled ComponentsのようなCSS-in-JSライブラリを使用する場合も、同様にデフォルトCSSをインポートし、スタイルを定義できます。または、カスタム入力コンポーネント(customInput)と組み合わせて、入力部分を完全にStyled Componentsでスタイリングすることも可能です。

    “`jsx
    import styled from ‘styled-components’;
    import DatePicker from ‘react-datepicker’;
    import “react-datepicker/dist/react-datepicker.css”; // デフォルトCSSもインポート

    // Styled DatePicker コンポーネントを作成
    const StyledDatePicker = styled(DatePicker)`
    / ここに DatePicker コンポーネント自体のスタイルを記述 /
    border: 1px solid blue;
    padding: 8px;
    border-radius: 4px;

    / 内部要素のスタイルは子孫セレクタで記述 /
    .react-datepicker {
    font-family: ‘Verdana’, sans-serif;
    }

    .react-datepicker__day–selected {
    background-color: blue;
    color: white;
    }
    `;

    function StyledComponentExample() {
    const [selectedDate, setSelectedDate] = useState(null);

    return (
        <div>
            <h2>Styled Components でスタイリング</h2>
            <StyledDatePicker
                selected={selectedDate}
                onChange={date => setSelectedDate(date)}
            />
        </div>
    );
    

    }
    “`
    Styled Componentsの場合でも、内部のカレンダー要素のスタイルを調整するには、子孫セレクタを使用するのが一般的です。

これらの方法を組み合わせて、アプリケーションのデザインガイドラインに沿ったDatepickerを作成できます。

5. 国際化 (Internationalization – i18n)

日付の表示形式や曜日の名前などは、国や地域によって異なります。React Datepickerは国際化(i18n)に対応しており、様々な言語で表示することができます。

国際化のためには、以下のステップが必要です。

  1. 使用したいロケールデータ(言語と地域の定義)をインポートする。
  2. DatePickerコンポーネントにlocale propでロケールを指定する。

React Datepickerは内部でdate-fnsを使用しているため、date-fnsが提供するロケールデータをインポートして使用します。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;

// date-fnsから日本語ロケールをインポート
import { ja } from ‘date-fns/locale’;
// 他のロケールも同様にインポートできます (例: enUS, fr, es など)
// import { enUS } from ‘date-fns/locale’;

function InternationalizedDatePicker() {
const [selectedDate, setSelectedDate] = useState(null);

const handleDateChange = (date) => {
setSelectedDate(date);
};

return (

国際化対応 (日本語)

  <h2>国際化対応 (英語)</h2>
  <DatePicker
    selected={selectedDate}
    onChange={handleDateChange}
    // locale={enUS} // 英語ロケールを指定 (インポートが必要)
    // locale prop を指定しない場合、デフォルトで英語になります
    dateFormat="MMMM d, yyyy EEEE" // 英語に合わせた表示形式
  />
</div>

);
}

export default InternationalizedDatePicker;
“`

date-fnsのロケールデータは、date-fns/localeディレクトリ以下に各言語コード(例: ja.js, en-US.js, fr.jsなど)として存在します。必要なロケールをインポートし、DatePickerlocale propに渡すだけです。

これにより、カレンダーの曜日の名前、月の名前、そしてdateFormat propで指定した形式(EEEEなどのロケール依存の形式指定子を使用した場合)が、指定したロケールに基づいて表示されるようになります。

アプリケーションのユーザー設定などに応じて、動的にlocale propを切り替えることで、複数の言語に対応したDatepickerを実装できます。

6. フォーム連携

React Datepickerを、標準的なHTMLフォームやreact-hook-formFormikのようなフォームライブラリと連携させて使用する方法を解説します。

標準的なHTMLフォーム要素としての使い方

React Datepickerは、内部で<input type="text">要素をレンダリングするため、基本的なHTMLフォームの一部として機能します。name propを設定することで、フォーム送信時にその名前で日付の値を取得できます。

ただし、フォーム送信時に渡される値は入力フィールドに表示されている文字列(dateFormatで指定された形式)になります。これをサーバーサイドやJavaScript側でDateオブジェクトとして扱うには、再度パース(解析)する必要があります。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;

function SimpleFormDatePicker() {
const [selectedDate, setSelectedDate] = useState(null);

// フォーム送信時のハンドラ (ここでは例としてログ出力)
const handleSubmit = (event) => {
event.preventDefault();
const formData = new FormData(event.target);
const dateString = formData.get(‘eventDate’);
console.log(‘フォームから取得した日付文字列:’, dateString);

// 取得した文字列をDateオブジェクトに戻す必要がある場合
// const parsedDate = new Date(dateString); // または date-fns の parse/parseISO など
// console.log('パースされたDateオブジェクト:', parsedDate);

};

return (

標準フォーム連携


setSelectedDate(date)}
dateFormat=”yyyy-MM-dd” // フォーム送信に適した形式 (ISO 8601 など)
placeholderText=”YYYY-MM-DD”
/>


);
}

export default SimpleFormDatePicker;
``
フォーム送信時の値は文字列であるため、データ型の整合性に注意が必要です。サーバーサイドでパースするか、フォーム送信前にクライアントサイドで適切な形式(例: ISO 8601形式の文字列、Unixタイムスタンプなど)に変換してから送信するのが一般的です。
dateFormatpropに“yyyy-MM-dd”“yyyy-MM-dd’T’HH:mm:ss”`などの標準的な形式を指定しておくと、後続の処理が容易になります。

react-hook-formFormikとの連携

react-hook-formFormikのような宣言的なフォームライブラリを使用する場合、Datepickerをカスタム入力フィールドとして登録する必要があります。これらのライブラリは通常、各入力フィールドの状態管理をHooksやHOC(Higher-Order Component)で行い、変更イベントをハンドリングして内部状態を更新します。

react-hook-formの場合、Controllerコンポーネントを使用するのが推奨される方法です。Controllerは、外部ライブラリ(この場合react-datepicker)が管理する入力フィールドをreact-hook-formの状態と同期させるためのラッパーです。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
import { useForm, Controller } from ‘react-hook-form’; // react-hook-form からインポート

function ReactHookFormDatePicker() {
// useForm フックを初期化
const { handleSubmit, control, formState: { errors } } = useForm({
// デフォルト値やバリデーションスキーマを設定可能
});

// フォーム送信時のハンドラ
const onSubmit = (data) => {
console.log(“フォームデータ:”, data);
// data.eventDate は Date オブジェクトになります
if (data.eventDate instanceof Date) {
console.log(“選択された日付 (Dateオブジェクト):”, data.eventDate.toISOString());
}
if (data.eventTime instanceof Date) {
console.log(“選択された時間 (Dateオブジェクト):”, data.eventTime.toISOString());
}

};

return (

React Hook Form 連携


{/ Controller コンポーネントで DatePicker をラップ /}
( // DatePicker をレンダリングする関数

)}
/>
{errors.eventDate &&

{errors.eventDate.message}

}

    <br />

    <div>
      <label>イベント開始時間:</label>
      <Controller
        name="eventTime"
        control={control}
         rules={{ required: '時間は必須です' }}
        render={({ field }) => (
          <DatePicker
             selected={field.value}
             onChange={field.onChange}
             onBlur={field.onBlur}
             ref={field.ref}
             showTimeSelect // 時間選択モード
             showTimeSelectOnly // 日付なし時間のみモード
             timeCaption="時間"
             dateFormat="HH:mm" // 時間のみの表示形式
             placeholderText="HH:MM"
          />
        )}
      />
       {errors.eventTime && <p style={{ color: 'red' }}>{errors.eventTime.message}</p>}
    </div>

    <button type="submit" style={{ marginTop: '20px' }}>送信</button>
  </form>
</div>

);
}

export default ReactHookFormDatePicker;
“`

Controllerコンポーネントは、以下の主要なpropを受け取ります。

  • name: フォームデータにおけるこのフィールドの名前。
  • control: useForm()フックから返されるcontrolオブジェクト。
  • rules: このフィールドに対するバリデーションルール(例: required)。
  • render: Datepickerコンポーネントをレンダリングするための関数。この関数は、fieldオブジェクトを含む引数を受け取ります。fieldオブジェクトには、value(現在の値)、onChange(値変更ハンドラ)、onBlur(フォーカスアウトハンドラ)、ref(入力要素へのref)が含まれています。これらの値をDatepickerコンポーネントの対応するpropに渡します。

この方法を使用すると、react-hook-formがDatepickerの状態(選択された日付)を自動的に管理し、フォーム送信時にはJavaScriptのDateオブジェクトとして値を取得できます。バリデーションルールもrules propで簡単に設定できます。

Formikなど他のフォームライブラリでも、似たようなパターン(カスタムフィールドとしてラップし、ライブラリが提供するvalueonChangeをDatepickerに渡す)で連携が可能です。多くの場合、FormikFieldFastFieldコンポーネントと、カスタムの入力コンポーネントを組み合わせて使用することになります。

7. バリデーション

日付入力フィールドのバリデーションは重要です。例えば、必須入力、特定の日付範囲内であること、特定のフォーマットであることなどをチェックします。

React Datepicker自体には、複雑なバリデーション機能は組み込まれていませんが、提供されるpropやイベントハンドラ、あるいは前述のフォームライブラリと連携することで、バリデーションを実装できます。

簡単な手動バリデーション (onChange内でチェック)

シンプルなバリデーションであれば、onChangeハンドラ内で直接チェックを行うことができます。

“`jsx
import React, { useState } from ‘react’;
import DatePicker from ‘react-datepicker’;
import “react-datepicker/dist/react-datepicker.css”;
import { isPast, addDays } from ‘date-fns’; // date-fnsで過去日付や未来日付を判定

function ManualValidationDatePicker() {
const [selectedDate, setSelectedDate] = useState(null);
const [error, setError] = useState(”);

const handleDateChange = (date) => {
setSelectedDate(date);
// バリデーション: 今日以降の日付のみ許可
if (date && isPast(date)) {
setError(‘過去の日付は選択できません’);
} else {
setError(”);
}

// 他のバリデーション例: 必須チェック
// if (!date) {
//     setError('日付は必須です');
// } else {
//     setError('');
// }

};

return (

手動バリデーション


{error &&

{error}

}

);
}

export default ManualValidationDatePicker;
“`

この方法では、ユーザーが日付を選択するたびにバリデーションロジックが実行され、エラーメッセージを表示・非表示させることができます。ただし、これはリアルタイムのバリデーションに近く、フォーム全体の送信前バリデーションとは切り離して考える必要があります。フォーム全体の送信前バリデーションは、フォームのonSubmitハンドラで行うか、フォームライブラリに任せるのが一般的です。

フォームライブラリを使ったバリデーション

react-hook-formFormikなどのフォームライブラリは、バリデーションルールを定義し、フォーム送信時や入力値変更時に自動的にバリデーションを実行する機能を提供しています。セクション6で解説したControllerを使った連携は、バリデーションも非常に容易にします。

Controllerrules propにバリデーションルール(例: { required: '日付は必須です', validate: value => isFuture(value) || '過去の日付は選択できません' })をオブジェクト形式で指定するだけで、ライブラリがバリデーションを実行し、エラーメッセージを管理してくれます。

jsx
// セクション6の ReactHookFormDatePicker コンポーネントの抜粋
// validation: 今日以降、かつ、今日から30日以内の日付のみ許可
rules={{
required: '日付は必須です',
validate: value => {
if (!value) return true; // required でチェック済み
const today = new Date();
const thirtyDaysLater = addDays(today, 30);
if (isPast(value)) {
return '過去の日付は選択できません';
}
if (value > thirtyDaysLater) {
return '30日より先の未来の日付は選択できません';
}
return true; // バリデーション成功
}
}}

フォームライブラリを使うと、バリデーションロジックがフォームの状態管理と統合されるため、より堅牢で管理しやすいバリデーションシステムを構築できます。

minDate, maxDateなど組み込みの制限によるバリデーション

minDate, maxDate, excludeDates, includeDates, filterDateなどのpropは、カレンダー上で選択可能な日付を物理的に制限します。これは、ある種のバリデーション(例: 必須の日付範囲制限)をUIレベルで実現する非常に効果的な方法です。ユーザーはそもそも無効な日付を選択できないため、後続のバリデーションエラーを防ぐことができます。

これらの組み込み制限と、手動バリデーションまたはフォームライブラリによるバリデーションを組み合わせることで、ユーザーにとって使いやすく、かつ要件を満たすバリデーションを実現できます。

8. パフォーマンスに関する考慮事項

ほとんどのユースケースにおいて、React Datepickerのパフォーマンスは問題になりません。しかし、非常に広い日付範囲(例えば、100年分以上のデータ)を扱う場合や、excludeDatesincludeDatesに非常に長い配列(数千、数万件)を渡す場合など、特定の状況ではパフォーマンスが低下する可能性があります。

パフォーマンスが懸念される場合のヒント:

  • 不要なpropは渡さない: 必要ない機能(時間選択など)は無効にしておきます。
  • 大きなリストの最適化: excludeDatesincludeDatesに渡す配列が非常に大きい場合、それらのリストの生成や処理に時間がかかる可能性があります。可能であれば、範囲制限(minDate, maxDate)やfilterDate関数を使った条件による除外・包含を検討します。filterDateは各日付に対して関数を実行するため、その関数内で複雑な処理を行わないように注意が必要です。
  • レンダリングの最適化: Datepicker自体が頻繁に再レンダリングされることでパフォーマンス問題が発生する場合、親コンポーネントの最適化(React.memoの使用、不要なstate更新の回避など)を検討します。

ただし、これらのパフォーマンスに関する懸念は、ごく特殊なケースに限定されることが多いです。一般的な日付選択機能では、デフォルト設定で十分なパフォーマンスが得られます。

9. よくある質問 (FAQ)

日付オブジェクトの取り扱い(Date, Date-fns, Moment.js)

React Datepickerは、入力としてJavaScriptの標準Dateオブジェクトを受け取り、onChangeでもDateオブジェクトを返します。

以前はMoment.jsが日付操作ライブラリとしてよく使われていましたが、Moment.jsは開発が停止されており、バンドルサイズが大きいという欠点があります。現在では、date-fnsやLuxonといったライブラリが推奨されています。

  • date-fns: 軽量で関数型プログラミングスタイルを取り入れており、個々の関数だけをインポートできるためバンドルサイズを小さく保てます。React Datepickerの公式ドキュメントでも推奨されています。
  • Luxon: Moment.jsの後継を目指して開発されており、不変性や国際化に強く設計されています。

どちらのライブラリを使用する場合でも、React Datepickerとの連携はスムーズです。ライブラリの関数で日付を操作・フォーマットし、結果をDateオブジェクトとしてDatePickerに渡す、あるいはDatePickerから受け取ったDateオブジェクトをライブラリの関数で処理するという流れになります。

特定のフレームワーク(Next.js, Gatsbyなど)での使用

React Datepickerはクライアントサイドで動作するコンポーネントです。Next.jsやGatsbyのようなサーバーサイドレンダリング(SSR)や静的サイト生成(SSG)を行うフレームワークで使用する場合、初期レンダリング時にブラウザのwindowオブジェクトなどに依存するコードが含まれているとエラーになる可能性があります。

React Datepickerは、その性質上、ブラウザ環境に依存する部分があります(例: カレンダーのポップアップ表示)。SSR環境でDatePickerを含むページをレンダリングすると、サーバー側でDatepickerのコンポーネントが評価され、エラーが発生する可能性があります。

対策としては、以下が挙げられます。

  • 動的インポート (dynamic): Next.jsの場合は、next/dynamicを使用してDatepickerコンポーネントを動的にインポートし、クライアントサイドでのみレンダリングされるようにします。

    “`jsx
    import dynamic from ‘next/dynamic’;

    // クライアントサイドでのみロード
    const DatePicker = dynamic(() => import(‘react-datepicker’), {
    ssr: false, // サーバーサイドではレンダリングしない
    });

    function MyPage() {
    const [selectedDate, setSelectedDate] = useState(null);
    // DatePicker を使用
    return ;
    }
    “`

  • useEffect 内でのインポート: SSR/SSG フレームワーク以外でも、クライアントサイドでのみ特定のコンポーネントをレンダリングしたい場合は、useStateuseEffectを組み合わせて、マウント後に動的にインポート&レンダリングする方法もあります。

これらの方法で、SSR/SSG環境でのエラーを回避できます。

モバイル対応

React Datepickerは基本的なモバイル対応が考慮されていますが、デフォルトのポップアップ表示はモバイルでの操作性が最適ではない場合があります。

モバイル対応を向上させるには:

  • withPortal prop: withPortaltrueにすると、カレンダーがスクリーンの中心にモーダル表示されるようになり、モバイルでの操作性が向上します。
  • カスタム入力 + フルスクリーンモーダル: customInput propを使用して入力フィールドを完全に制御し、クリック時に独自のフルスクリーンモーダルを開き、その中にinlineモードで表示したDatePickerを配置するという方法も考えられます。これにより、モバイルフレンドリーなUIを完全に自由に設計できます。
  • CSSの調整: モバイル向けのCSSメディアクエリを使用して、カレンダーのサイズやフォントサイズなどを調整します。

TypeScriptでの型定義

React DatepickerはTypeScriptフレンドリーです。npmパッケージには型定義ファイルが含まれているため、TypeScriptプロジェクトで追加の型定義ライブラリ(@types/...)をインストールする必要はありません。プロパティやイベントハンドラの引数などは適切に型付けされています。

selected propやonChangeハンドラから受け取る日付の値は、Date型またはnull型として扱えます。

10. まとめ

この記事では、React Datepickerライブラリのインストールから始まり、基本的な日付選択機能、日付範囲選択、時間選択、月/年選択といった高度な機能、特定の期間や日付の制限、カスタム入力やカレンダー表示のカスタマイズ、国際化、そしてフォーム連携やバリデーションに至るまで、React Datepickerの様々な側面を網羅的に解説しました。

React Datepickerは、その豊富なプロパティと柔軟なカスタマイズ性により、多様な日付選択に関する要件に対応できる強力なコンポーネントです。デフォルトスタイルである程度の見た目が提供されているため、すぐに導入して基本的な機能を利用できます。さらに、CSSによるスタイリングやcustomInput, renderDayContents, renderCustomHeaderといったプロパティを駆使すれば、アプリケーションのUX/UIデザインに合わせて完全に統合されたDatepickerを構築することも可能です。

フォームライブラリとの連携もスムーズに行えるため、実際の業務アプリケーションでも扱いやすいでしょう。国際化対応も容易であり、グローバルなアプリケーション開発にも適しています。

もちろん、この記事で紹介したプロパティや機能は全てではありません。React Datepickerの公式ドキュメントには、さらに詳細な情報やその他のプロパティに関する説明が記載されています。この記事を足がかりとして、公式ドキュメントを参照したり、実際にコードを書きながら実験したりすることで、React Datepickerをより深く理解し、使いこなせるようになるでしょう。

日付や時間に関するUIが必要なあなたのReactプロジェクトに、ぜひReact Datepickerを導入してみてください。

Happy Coding!


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール