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


Go to the next lesson