📅

Y-M-Dドロップダウン式 React date picker ライブラリ

2022/05/27に公開1

react-ymd-date-select

Y-M-D(年月日)ドロップダウン式の日付選択UIのためのReactコンポーネントライブラリ react-ymd-date-selectを作りました。

react-ymd-date-select sample screenshot

whitphx/react-ymd-date-select - GitHub

要件・目的によっては、Y-M-D選択式UIの方が一般的なカレンダーUIより使いやすいことがあります。
例えば誕生日選択では、カレンダーUIは往々にして大昔へ遡るのが面倒な上、ユーザとしては入力したい日付はすでにはっきりわかっており、カレンダーを見て日付を選ぶ必要もないため利点もありません[1]

実際に日付選択ドロップダウンを作りたい場面に遭遇したのですが、その目的のための既存のライブラリが見つかりませんでした。かといって自分で作ろうとすると単純に見えて意外と面倒なことが多いです。

  • 年、月、日それぞれのArrayの生成
  • 無効な年、月、日の組み合わせの検知
  • 3つの<select />の値を合成し1つのDate Stringにして親コンポーネントやReact Hook FormなどのフォームライブラリにonChangeで伝える、また親からきたvalueを分解して3つの<select />にセットする

また、アプリケーションによっては追加で以下のような要件もありえます

  • 年にデフォルト値を指定したい
  • 日のドロップダウンを隠したい

これらをまとめて扱うために react-ymd-date-select を作りました。
このライブラリの useDateSelect() フックで、下記の例のようにアプリケーション用の独自のY-M-Dドロップダウンコンポーネントを作れます。上記のような面倒はライブラリに任せてViewロジックにのみ集中できます。

このライブラリの valueonChange の引数は yyyy-MM-DD 形式の文字列です。これはISO8601で定義されたフォーマットで、かつブラウザ標準の <input type="date" /> が返す値の形式と同じです。参考:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date#value

APIの詳細や他のサンプルなどについてはデモページをご覧ください。

import { useState } from "react";
import { useDateSelect } from "react-ymd-date-select";

interface CustomDateSelectProps {
  onChange: (value: string) => void;
  value: string;
}
function CustomDateSelect(props: CustomDateSelectProps) {
  const dateSelect = useDateSelect(props.value, props.onChange);

  return (
    <>
      <input
        type="date"
        value={dateSelect.dateValue || ""}
        onChange={dateSelect.onDateChange}
      />
      <label>
        Year
        <select value={dateSelect.yearValue} onChange={dateSelect.onYearChange}>
          {dateSelect.yearOptions.map((yearOption) => (
            <option key={yearOption.value} value={yearOption.value}>
              {yearOption.label}
            </option>
          ))}
        </select>
      </label>
      <label>
        Month
        <select
          value={dateSelect.monthValue}
          onChange={dateSelect.onMonthChange}
        >
          {dateSelect.monthOptions.map((monthOption) => (
            <option key={monthOption.value} value={monthOption.value}>
              {monthOption.label}
            </option>
          ))}
        </select>
      </label>
      <label>
        Day
        <select value={dateSelect.dayValue} onChange={dateSelect.onDayChange}>
          {dateSelect.dayOptions.map((dayOption) => (
            <option key={dayOption.value} value={dayOption.value}>
              {dayOption.label}
            </option>
          ))}
        </select>
      </label>
    </>
  );
}

英語版: https://dev.to/whitphx/a-react-library-for-y-m-d-dropdown-date-picker-ecp

脚注
  1. その点では書式を制限したtext_inputがベストになる可能性もありますね。スマホ操作時はやはり少なくとも月・日についてはドロップダウンの方が使いやすいかもしれません。 ↩︎

Discussion

OskarOskar

素晴らしいです!
でも、これはできないらしい。。。