はじめに
react-date-rangeはカレンダーのUIから日付を選択できるライブラリ。
https://github.com/hypeserver/react-date-range
基本的な使い方
基本的な使い方はとてもシンプル
<DateRange
onRangeFocusChange={onSelectPeriod} // 後述
onChange={(range) => postDate(range)} // 日付をクリック等で指定した際に発火
moveRangeOnFirstSelection={false} // trueにするとクリックした日に範囲が限定される。false時はstartとendを指定した際に範囲が決定される
months={2} // defaultで一画面上に表示される月の数
ranges={[
{
startDate: Date型の値,
endDate: Date型の値,
key: "selection" // 後述
}
]} // ここに指定したstartとendが選択中の期間として設定される。
direction="horizontal" // 縦か横か
locale={jaLocale} // 言語設定
dateDisplayFormat={"yyyy/MM/dd"} // 日付表示のフォーマット
monthDisplayFormat={"yyyy年MMM"} // 月表示のフォーマット
maxDate={endOfToday()} // 指定できる最大未来
minDate={new Date(2000, 1, 1)} // 指定できる最古過去
/>
まじこれだけ。これ以外にもたくさんパラメータある。詳細はこちら。
endDate選択時のみにアクションを発行する
onChange及びその他のonChange系列のアクション(onRangeFocusChangeも含む)の発火タイミングは日付をクリック等で指定したタイミングになっている。
すなわち、startとendを日付のクリックで決めると、2回onChangeが走る。
これだと単純にonChangeでサーバーにリクエストを送ってデータをfetchする場合、無駄なリクエストがstartのみを選択した瞬間に発生してしまう。だが、onChangeにはstartだけの選択なのか、endを選択したのかを示すようなパラメータが存在していない。
その情報はonRangeFocusChangeの引数に入っている。react-date-rangeはそれを[0, 0]または[0, 1]で表現している。
[0, 0]はstart/end両方を指定した時、[0, 1]はstartのみを指定したときである。
この情報をreduxやlocal stateで管理してその値を参照して、リクエストをサーバーに飛ばすか飛ばさないかを決めればいい。
しかし、onRangeFocusChangeの引数はこの[0, 1]とかの情報のみで、選択した日時の情報はない。
なので現状onChangeとonRangeFocusChangeを組み合わせる必要がある。
ローカルstateでやるならこんな感じかと。
const [isPeriodSelectionFinished, setIsPeriodSelectionFinished] = useState(true);
useEffect(() => {
if (isPeriodSelectionFinished) {
// post処理
}
})
return (
<DateRange
onRangeFocusChange={(props) => setIsPeriodFinished(_.isEqual(props, [0,0]))}
onChange={(range) => postDate(range)} // 日付をクリック等で指定した際に発火
moveRangeOnFirstSelection={false} // trueにするとクリックした日に範囲が限定される。false時はstartとendを指定した際に範囲が決定される
months={2} // defaultで一画面上に表示される月の数
ranges={[
{
startDate: Date型の値,
endDate: Date型の値,
key: "selection"
}
]} // ここに指定したstartとendが選択中の期間として設定される。
direction="horizontal" // 縦か横か
locale={jaLocale} // 言語設定
dateDisplayFormat={"yyyy/MM/dd"} // 日付表示のフォーマット
monthDisplayFormat={"yyyy年MMM"} // 月表示のフォーマット
maxDate={endOfToday()} // 指定できる最大未来
minDate={new Date(2000, 1, 1)} // 指定できる最古過去
/>
)
いやユースケース的にend決定時に発火するonEndChange的なやつ作れ。
せめてonRangeFocusChangeの情報とonChangeの情報をどっちかに寄せて、どっちか使えば済むようにはしといてほしかったよね。
参考:https://github.com/hypeserver/react-date-range/issues/400