So now we are ready to configure the calendar.
Let’s start by setting the format for the dates.
I found some instructions in the date picker documentation, and I’m going to follow them.
First install date-fns
. This is a library similar to Moment.js, if you are familiar with it, except it allows us to have a smaller size in our bundle, because we can cherry-pick the functions we need from it.
npm install date-fns
Then we import the date-fns/format
and date-fns/parse
functions in the DateRangePicker.js component:
components/DateRangePicker.js
import dateFnsFormat from 'date-fns/format'
import dateFnsParse from 'date-fns/parse'
and we define the parseDate
and formatDate
functions:
const parseDate = (str, format, locale) => {
const parsed = dateFnsParse(str, format, new Date(), { locale })
return DateUtils.isDate(parsed) ? parsed : null
}
const formatDate = (date, format, locale) =>
dateFnsFormat(date, format, { locale })
We’ll pass them to the DayPickerInput
component.
We also define the format for the date. I like the format day monthname year, for example 20 Nov 2019
. This is how we define it:
const format = 'dd MMM yyyy'
Cool! Now in the JSX we change <DayPickerInput />
to
<DayPickerInput
formatDate={formatDate}
format={format}
parseDate={parseDate}
placeholder={`${dateFnsFormat(new Date(), format)}`}
/>
in the 2 places where it appears.
Then we need to disable selecting all dates in the past.
Why? Because we can’t book dates in the past. Only in the future. We can’t go back in time.
We can do so by configuring DayPickerInput
. I found a guide in https://react-day-picker.js.org/docs/matching-days in “Matching days with modifiers” but this was talking about the DayPicker
component, which is a different one thatn hte DayPickerInput
we’re using.
DayPicker
is the calendar that appears when we click the input element with the formatted date.
We can pass properties to DayPicker
by using the dayPickerProps
prop on DayPickerInput
:
<DayPickerInput
formatDate={formatDate}
format={format}
parseDate={parseDate}
placeholder={`${dateFnsFormat(new Date(), format)}
`}
dayPickerProps={{
modifiers: {
disabled: {
before: new Date()
}
}
}}
/>
This part is a little confusing, but every time we use a library, we must first understand how it works from the docs, and adapt to it. It’s always work we need to do.
In this particular case, I found the docs about dayPickerProps
in this page: https://react-day-picker.js.org/docs/input, in “Customizing the DayPicker”.
Ok so now that we denied selecting dates in the past, let’s add 2 variables in the components/DateRangePicker.js
component, and we update them when the selected dates change:
components/DateRangePicker.js
import { useState } from 'react'
///
export default () => {
const [startDate, setStartDate] = useState(new Date())
const [endDate, setEndDate] = useState(new Date())
return (
//...the component JSX
)
}
Now, inside the JSX we add a new prop to DayPickerInput
to update those state variables when a new date has been selected:
<DayPickerInput
formatDate={formatDate}
format={format}
parseDate={parseDate}
placeholder={`${dateFnsFormat(new Date(), format)}`}
dayPickerProps={{
modifiers: {
disabled: {
before: new Date()
}
}
}}
onDayChange={day => {
setStartDate(day)
}}
/>
and here’s the end date
<DayPickerInput
formatDate={formatDate}
format={format}
parseDate={parseDate}
placeholder={`${dateFnsFormat(new Date(), format)}`}
dayPickerProps={{
modifiers: {
disabled: {
before: new Date()
}
}
}}
onDayChange={day => {
setEndDate(day)
}}
/>
The code for this lesson is available at https://github.com/flaviocopes/airbnb-clone-react-nextjs/commit/8bed96502ef95a3c8a92ec3872a4b379f46213f8